Skip to content

Commit

Permalink
#601: naming classes, local functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jand42 committed Aug 28, 2016
1 parent f057cb6 commit 778e380
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 41 deletions.
77 changes: 51 additions & 26 deletions src/compiler/WebSharper.Compiler/Breaker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type Broken<'a> =
{
Body : 'a
Statements : Statement list
Variables : Id list
Variables : (Id * Statement option) list
}

let broken b =
Expand All @@ -64,7 +64,7 @@ let bindBroken f b =
}

let private getExpr b = match b with ResultVar v -> Var v | ResultExpr e -> e
let private getVarList b = match b with ResultVar v -> [ v ] | ResultExpr e -> []
let private getVarList b = match b with ResultVar v -> [ v, None ] | ResultExpr e -> []

let toBrExpr b =
{
Expand Down Expand Up @@ -117,18 +117,30 @@ type MarkApplicationsPure(v) =
ReplaceId(id, v).TransformExpression(body) |> this.TransformExpression
| _ -> base.TransformLet(id, value, body)

let toDecls (vars: _ list) =
seq {
for vv in vars do
match vv with
| v, None -> yield VarDeclaration(v, Undefined)
| _ -> ()
for vv in vars do
match vv with
| _, Some s -> yield s
| _ -> ()
}

let toStatements f b =
let b = toBrExpr b
seq {
for v in b.Variables -> VarDeclaration(v, Undefined)
yield! toDecls b.Variables
yield! b.Statements
yield f b.Body
}

let toStatementsL f (b: Broken<BreakResult>)=
let b = toBrExpr b
seq {
for v in b.Variables -> VarDeclaration(v, Undefined)
yield! toDecls b.Variables
yield! b.Statements
yield! f b.Body
}
Expand All @@ -142,13 +154,13 @@ let toStatementExpr b =
match b.Body with
| ResultVar v ->
seq {
for v in b.Variables -> VarDeclaration(v, Undefined)
yield! toDecls b.Variables
for st in b.Statements ->
TransformVarSets(v, id).TransformStatement(st)
}
| ResultExpr e ->
seq {
for v in b.Variables -> VarDeclaration(v, Undefined)
yield! toDecls b.Variables
yield! b.Statements
if not (isPureExpr e) then
yield ExprStatement (ignoreVoid e)
Expand Down Expand Up @@ -205,15 +217,15 @@ let rec breakExpr expr : Broken<BreakResult> =
bL true (b.Variables @ accVar, accSt, b.Body :: accE) bRest
else
let v = Id.New()
bL true (v :: b.Variables @ accVar, VarSetStatement (v, getExpr b.Body) :: accSt, ResultVar v :: accE) bRest
bL true ((v, None) :: b.Variables @ accVar, VarSetStatement (v, getExpr b.Body) :: accSt, ResultVar v :: accE) bRest
else
bL false (b.Variables @ accVar, accSt, b.Body :: accE) bRest
else
if isStronglyPureOrResultVar b.Body then
bL true (b.Variables @ accVar, b.Statements @ accSt, b.Body :: accE) bRest
else
let v = Id.New()
bL true (v :: b.Variables @ accVar, b.Statements @ VarSetStatement (v, getExpr b.Body) :: accSt, ResultVar v :: accE) bRest
bL true ((v, None) :: b.Variables @ accVar, b.Statements @ VarSetStatement (v, getExpr b.Body) :: accSt, ResultVar v :: accE) bRest
let vars, st, e = bL false ([], [], []) (List.rev bb)
{
Body = e
Expand Down Expand Up @@ -308,7 +320,7 @@ let rec breakExpr expr : Broken<BreakResult> =
else
brA.Statements |> List.map (TransformMoreVarSets(removeVars, id).TransformStatement)
@ (extraExprs |> List.map ExprStatement)
Variables = brA.Variables |> List.filter (fun v -> removeVars |> List.contains v |> not)
Variables = brA.Variables |> List.filter (fun (v, _) -> removeVars |> List.contains v |> not)
}
| NewArray a ->
brL a |> mapBroken NewArray
Expand Down Expand Up @@ -395,13 +407,13 @@ let rec breakExpr expr : Broken<BreakResult> =
{
Body = ResultVar a
Statements = brB.Statements |> List.map (TransformVarSets(v, fun e -> VarSet(a, e)).TransformStatement)
Variables = [ a ]
Variables = brB.Variables
}
| ResultExpr e ->
{
Body = ResultExpr (Void (VarSet(a, e)))
Statements = brB.Statements
Variables = [ a ]
Variables = [ a, None ] @ brB.Variables
}
| StatementExpr (I.ExprStatement a, None) ->
br a
Expand All @@ -410,7 +422,7 @@ let rec breakExpr expr : Broken<BreakResult> =
{
Body = ResultExpr (Sequential [brA.Body; Var b])
Statements = brA.Statements
Variables = b :: brA.Variables
Variables = (b, None) :: brA.Variables
}
| StatementExpr (st, v) ->
{
Expand Down Expand Up @@ -450,14 +462,24 @@ let rec breakExpr expr : Broken<BreakResult> =
| Let (var, value, I.Function ([x], (I.ExprStatement(I.Application (I.Var f, [I.Var y], _, _)) | I.Return(I.Application (I.Var f, [I.Var y], _, _)))))
when f = var && x = y ->
br value
| Let(a, IgnoreSourcePos.Var b, c)
| Let(a, b, I.Var c) when a = c ->
br b
| Let(a, I.Var b, c)
when (not b.IsMutable) || (notMutatedOrCaptured a c && notMutatedOrCaptured b c) -> // TODO: maybe weaker check is enough
ReplaceId(a, b).TransformExpression(c) |> br
| Let(var, value, I.Application(func, [I.Var v], p, l))
when v = var && isStronglyPureExpr func && CountVarOccurence(var).Get(func) = 0 ->
Application(func, [value], p, l) |> br
| Let (objVar, I.Object objFields, I.Sequential (PropSetters (setters, v))) when v = objVar ->
objFields @ setters |> Object |> br
| Let(var, I.Function(args, body), c)
when notMutatedOrCaptured var c && CountVarOccurence(var).Get(c) >= 2 ->
let brC = br c
{
Body = brC.Body
Statements = brC.Statements
Variables = (var, Some (FuncDeclaration(var, args, BreakStatement body))) :: brC.Variables
}
| Let(a, b, c) ->
let brB = br b
match brB.Body with
Expand Down Expand Up @@ -489,7 +511,7 @@ let rec breakExpr expr : Broken<BreakResult> =
{
Body = ResultExpr(Sequential [VarSet (a, brB.Body); brC.Body ])
Statements = []
Variables = a :: brB.Variables @ brC.Variables
Variables = (a, None) :: brB.Variables @ brC.Variables
}
else
{
Expand All @@ -504,7 +526,7 @@ let rec breakExpr expr : Broken<BreakResult> =
{
Body = ResultExpr(Sequential [VarSet (a, brB.Body); brC.Body ])
Statements = brB.Statements
Variables = a :: brB.Variables @ brC.Variables
Variables = (a, None) :: brB.Variables @ brC.Variables
}
else
{
Expand All @@ -519,13 +541,13 @@ let rec breakExpr expr : Broken<BreakResult> =
Statements =
(brB.Statements |> List.map (TransformVarSets(bv, fun e -> VarSet(a, e)).TransformStatement))
@ brC.Statements
Variables = a :: brB.Variables @ brC.Variables
Variables = (a, None) :: brB.Variables @ brC.Variables
}
| NewVar(a, Undefined) ->
{
Body = ResultExpr(Undefined)
Statements = []
Variables = [ a ]
Variables = [ a, None ]
}
| NewVar(a, b) ->
let brB = br b
Expand All @@ -534,7 +556,7 @@ let rec breakExpr expr : Broken<BreakResult> =
{
Body = ResultExpr(VarSet (a, e))
Statements = brB.Statements
Variables = a :: brB.Variables
Variables = (a, None) :: brB.Variables
}
| ResultVar v ->
{
Expand Down Expand Up @@ -569,14 +591,12 @@ let rec breakExpr expr : Broken<BreakResult> =
Body = ResultExpr brB.Body
Statements =
[
for i, _ in a do
yield VarDeclaration(i, Undefined)
for i, v in brAs do
yield! v.Statements
yield VarSetStatement(i, v.Body)
yield! brB.Statements
]
Variables = brB.Variables
Variables = (brAs |> List.collect (fun (v, ba) -> (v, None) :: ba.Variables)) @ brB.Variables
}
| New(a, b) ->
brL (a :: b)
Expand Down Expand Up @@ -614,6 +634,8 @@ and private breakSt statement : Statement seq =
Seq.singleton (Labeled (a, combine (brS b)))
| VarDeclaration (a, b) ->
brE b |> toStatements (fun bE -> VarDeclaration (a, bE))
| FuncDeclaration (a, b, c) ->
Seq.singleton (FuncDeclaration (a, b, combine (brS c)))
| While (a, b) ->
let brA = brE a
if hasNoStatements brA then
Expand Down Expand Up @@ -644,7 +666,7 @@ and private breakSt statement : Statement seq =
else
let brB = brB |> toBrExpr
[
for v in brB.Variables -> VarDeclaration(v, Undefined)
yield! toDecls brB.Variables
yield DoWhile (combine (Seq.append (brS a) brB.Statements), brB.Body)
]
|> Seq.ofList
Expand All @@ -657,16 +679,19 @@ and private breakSt statement : Statement seq =
[
match brA with
| Some brA ->
yield! brA.Statements
for v in brA.Variables -> VarDeclaration(v, Undefined)
yield! toDecls brA.Variables
| _ -> ()
match brB with
| Some brB ->
for v in brB.Variables -> VarDeclaration(v, Undefined)
yield! toDecls brB.Variables
| _ -> ()
match brC with
| Some brC ->
for v in brC.Variables -> VarDeclaration(v, Undefined)
yield! toDecls brC.Variables
| _ -> ()
match brA with
| Some brA ->
yield! brA.Statements
| _ -> ()
yield For(get brA, get brB, get brC, combine (brS d))
]
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/WebSharper.Compiler/CompilationHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ module JSRuntime =
let private runtime = ["Runtime"; "IntelliFactory"]
let private runtimeFunc f p args = Application(GlobalAccess (Address (f :: runtime)), args, p, Some (List.length args))
let private runtimeFuncI f p i args = Application(GlobalAccess (Address (f :: runtime)), args, p, Some i)
let Class members basePrototype statics = runtimeFunc "Class" true [members; basePrototype; statics]
let Class members basePrototype statics name = runtimeFunc "Class" true [members; basePrototype; statics; Value (String name)]
let Ctor ctor typeFunction = runtimeFunc "Ctor" true [ctor; typeFunction]
let Cctor cctor = runtimeFunc "Cctor" true [cctor]
let GetOptional value = runtimeFunc "GetOptional" true [value]
Expand Down
31 changes: 26 additions & 5 deletions src/compiler/WebSharper.Compiler/JavaScriptWriter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,26 @@ type Environment =
mutable ScopeVars : Set<string>
mutable CompactVars : int
mutable ScopeIds : Map<Id, string>
ScopeFuncs : ResizeArray<J.ProgramElement>
}
static member New(name, pref) =
{
AssemblyName = name
Preference = pref
ScopeVars = Set.empty
CompactVars = 0
ScopeIds = Map.empty
ScopeIds = Map.empty
ScopeFuncs = ResizeArray()
}

member this.Clone() =
member this.NewInner() =
{
AssemblyName = this.AssemblyName
Preference = this.Preference
ScopeVars = this.ScopeVars
CompactVars = this.CompactVars
ScopeIds = this.ScopeIds
ScopeFuncs = ResizeArray()
}

let undef = J.Unary(J.UnaryOperator.``void``, J.Constant (J.Literal.Number "0"))
Expand Down Expand Up @@ -89,7 +92,6 @@ let rec transformExpr (env: Environment) (expr: Expression) : J.Expression =
match expr with
| Undefined -> undef
| This -> J.This
// | Global -> glob
| Var id -> J.Var (trI id)
| Value v ->
match v with
Expand Down Expand Up @@ -123,7 +125,7 @@ let rec transformExpr (env: Environment) (expr: Expression) : J.Expression =
} : J.SourcePos
J.ExprPos (trE e, jpos)
| Function (ids, b) ->
let innerEnv = env.Clone()
let innerEnv = env.NewInner()
let args = ids |> List.map (defineId innerEnv)
let body =
match b |> transformStatement innerEnv with
Expand All @@ -132,9 +134,10 @@ let rec transformExpr (env: Environment) (expr: Expression) : J.Expression =
| J.Return None :: more -> List.rev more
| _ -> b
|> List.map J.Action
| J.Empty
| J.Return None -> []
| b -> [ b |> J.Action ]
J.Lambda(None, args, body)
J.Lambda(None, args, List.ofSeq innerEnv.ScopeFuncs @ body)
| ItemGet (x, y)
| ItemGetNonPure (x, y)
-> (trE x).[trE y]
Expand Down Expand Up @@ -250,6 +253,8 @@ and transformStatement (env: Environment) (statement: Statement) : J.Statement =
emptyDecls.Add (defineId env id)
| _ ->
decls.Add (defineId env id, trE e)
| FuncDeclaration _ ->
trS a |> ignore
| Empty
| ExprStatement IgnoreSourcePos.Undefined -> ()
| ExprStatement (IgnoreSourcePos.Sequential s) ->
Expand Down Expand Up @@ -295,6 +300,22 @@ and transformStatement (env: Environment) (statement: Statement) : J.Statement =
| Return a -> J.Return (Some (trE a))
| VarDeclaration (id, e) ->
J.Vars ([defineId env id, match e with IgnoreSourcePos.Undefined -> None | _ -> Some (trE e)])
| FuncDeclaration (x, ids, b) ->
let id = defineId env x
let innerEnv = env.NewInner()
let args = ids |> List.map (defineId innerEnv)
let body =
match b |> transformStatement innerEnv with
| J.Block b ->
match List.rev b with
| J.Return None :: more -> List.rev more
| _ -> b
|> List.map J.Action
| J.Empty
| J.Return None -> []
| b -> [ b |> J.Action ]
J.Function(id, args, List.ofSeq innerEnv.ScopeFuncs @ body) |> env.ScopeFuncs.Add
J.Empty
| While(a, b) -> J.While (trE a, trS b)
| DoWhile(a, b) -> J.Do (trS a, trE b)
| For(a, b, c, d) -> J.For(Option.map trE a, Option.map trE b, Option.map trE c, trS d)
Expand Down
11 changes: 7 additions & 4 deletions src/compiler/WebSharper.Compiler/Packager.fs
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@ let packageAssembly (refMeta: M.Info) (current: M.Info) isBundle =
| M.Macro (_, _, Some fb) -> withoutMacros fb
| _ -> info

let rec packageClass (c: M.ClassInfo) =
let rec packageClass (c: M.ClassInfo) name =

match c.BaseClass with
| Some b ->
match classes.TryFind b with
| Some bc ->
classes.Remove b |> ignore
packageClass bc
packageClass bc b.Value.FullName
| _ -> ()
| _ -> ()

Expand Down Expand Up @@ -165,7 +165,7 @@ let packageAssembly (refMeta: M.Info) (current: M.Info) isBundle =
| _ -> Value Null

if c.HasWSPrototype then
packageCtor addr <| JSRuntime.Class prototype baseType (GlobalAccess addr)
packageCtor addr <| JSRuntime.Class prototype baseType (GlobalAccess addr) name

for info, _, body in c.Methods.Values do
match withoutMacros info with
Expand Down Expand Up @@ -194,7 +194,7 @@ let packageAssembly (refMeta: M.Info) (current: M.Info) isBundle =
while classes.Count > 0 do
let (KeyValue(t, c)) = classes |> Seq.head
classes.Remove t |> ignore
packageClass c
packageClass c t.Value.FullName

if isBundle then
match current.EntryPoint with
Expand All @@ -209,12 +209,15 @@ let packageAssembly (refMeta: M.Info) (current: M.Info) isBundle =
Application(Function([], Block allStatements), [], false, Some 0)

let exprToString asmName pref sourceMap statement =
let env = WebSharper.Compiler.JavaScriptWriter.Environment.New(asmName, pref)
let program =
statement
|> JavaScriptWriter.transformExpr (WebSharper.Compiler.JavaScriptWriter.Environment.New(asmName, pref))
|> WebSharper.Core.JavaScript.Syntax.Ignore
|> WebSharper.Core.JavaScript.Syntax.Action
|> fun x -> [ x ]
if env.ScopeFuncs.Count > 0 then
failwith "Unexpected top level function declaration found"
let w = WebSharper.Core.JavaScript.Writer.CodeWriter(?assemblyName = if sourceMap then Some asmName else None)
WebSharper.Core.JavaScript.Writer.WriteProgram pref w program
w.GetCodeFile(), w.GetMapFile()
Loading

0 comments on commit 778e380

Please sign in to comment.