Skip to content

Commit

Permalink
Still experimenting with walking the JS ast
Browse files Browse the repository at this point in the history
  • Loading branch information
colinbull committed Mar 18, 2012
1 parent 605ef14 commit 6537c3a
Showing 1 changed file with 44 additions and 20 deletions.
64 changes: 44 additions & 20 deletions Src/Javascript.TypeProvider/Parser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ open IronJS.Compiler

module Parser =

type TypeDef =
type TypeDef =
| TypeDef of TypeDef list
| Object of string * TypeDef list
| Method of string * seq<string>
| Method of uint64 * string * seq<string>

let private walkAst (scopeData : Parser.ScopeData) (ast : Ast.Tree) =
let scopeMap =
Expand All @@ -20,42 +21,65 @@ module Parser =

let methodDef n (scope : Ast.FunctionScope ref) =
match scopeMap.TryFind (!scope).Id with
| Some(scopeEntry) -> Method(n, !scopeEntry.Parameters)
| None -> Method(n, [])
| Some(scopeEntry) ->
if not <| String.IsNullOrEmpty(n)
then Some <| Method(scopeEntry.Id, n, !scopeEntry.Parameters)
else None
| None -> None

let addObject t = function
| Object(n, defns) -> Object(n, t :: defns)
| a -> failwithf "Could not enhance %A with a function" a
let addToObject methd =
Option.bind (fun s ->
match s with
| TypeDef(ns) -> Some <| TypeDef(methd:: ns)
| Object(n, defns) -> Some <| Object(n, methd :: defns)
| a -> None)

let addFunc scopedName scope = function
| Object(n, defns) -> Object(n, (methodDef scopedName scope) :: defns)
| Method(_,_) -> methodDef scopedName scope
let addFunc scopedName scope t =
methodDef scopedName scope
|> Option.fold (fun s methd -> addToObject methd s) t

let isPass = function
| Ast.Pass -> true
| _ -> false

let rec walk' (scopedName : string) (typedef : TypeDef) (tree : Ast.Tree) =
let rec walk' (scopedName : string) (typedef : TypeDef option) (tree : Ast.Tree) =
match tree with
| Ast.Function(_, scope, tree) ->
walk' "" (addFunc scopedName scope typedef) tree
| Ast.Property(tree, id) ->
printfn "Property %s" id
walk' id typedef tree
| Ast.Block(trees) ->
List.fold (walk' scopedName) typedef trees
List.fold (walk' scopedName) typedef (trees |> List.filter (not << isPass))
| Ast.Var(tree) ->
(walk' scopedName typedef tree)
| Ast.Assign(Ast.Identifier(id), tree) ->
walk' id typedef tree
| Ast.Assign(treeL, treeR) ->
walk' scopedName (walk' scopedName typedef treeL) treeR
| Ast.Object(properties) ->
Object(scopedName, List.map (fun (n,t) -> walk' (Method(n, []) t))
if not <| String.IsNullOrEmpty(scopedName)
then
let props =
properties
|> List.choose (fun (n, t) ->
match t with
| Ast.Function(_, scope, tree) -> methodDef n scope
| _ -> None
)
addToObject (Object(scopedName, props)) typedef
else typedef
| Ast.Return(tree) ->
walk' scopedName typedef tree
| Ast.Identifier(id) ->
walk' id typedef (Ast.Null)
| Ast.Invoke(Ast.Function(_, scope, tree), treeF) ->
walk' scopedName (addFunc scope typedef) tree
walk' scopedName typedef (Ast.Pass)
| Ast.Invoke(tree, treeF) ->
List.fold (walk' scopedName) (walk' scopedName typedef tree) treeF
| a ->
let (caseInfo, _) = Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(a, typeof<Ast.Tree>)
printfn "%s" (caseInfo.Name)
typedef

walk' "" (Object("", [])) ast
match walk' "" (Some <| TypeDef([])) ast with
| Some(TypeDef(v)) -> v |> List.rev
| _ -> []

let getTypeDefinition (filePath : string) =
let (ast, scopeData) = Parser.parseFile (Env()) filePath
Expand Down

0 comments on commit 6537c3a

Please sign in to comment.