-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build,compilerEs: support generating closure reflection info in js
- Loading branch information
Matthew Giannini
authored and
Matthew Giannini
committed
Mar 15, 2024
1 parent
5db784e
commit 33465b5
Showing
7 changed files
with
134 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// | ||
// Copyright (c) 2024, Brian Frank and Andy Frank | ||
// Licensed under the Academic Free License version 3.0 | ||
// | ||
// History: | ||
// 15 Mar 2024 Matthew Giannini Creation | ||
// | ||
|
||
using compiler | ||
|
||
** | ||
** JsClosure provides utilities for working with JS closures. | ||
** | ||
class JsClosure : JsNode | ||
{ | ||
new make(CompilerSupport s) : super(s) | ||
{ | ||
} | ||
|
||
Bool emitReflection() { c.input.jsReflectClosures } | ||
|
||
** Write the actual ClosureExpr | ||
Void writeClosure(ClosureExpr ce) | ||
{ | ||
|
||
CType[] sigTypes := [,].addAll(ce.signature.params).add(ce.signature.ret) | ||
isJs := sigTypes.all { !it.isForeign && checkJsSafety(it, loc) } | ||
if (isJs) | ||
{ | ||
if (emitReflection) | ||
{ | ||
js.wl("sys.Func.__reflect(").indent | ||
js.wl("${mapFuncSpec(ce)},", loc) | ||
} | ||
|
||
js.w("${methodParams(ce.doCall.params)}", loc).wl(" => {") | ||
js.indent | ||
old := plugin.thisName | ||
plugin.thisName = "this\$" | ||
writeBlock(ce.doCall.code) | ||
plugin.thisName = old | ||
js.unindent | ||
js.w("}") | ||
|
||
if (emitReflection) | ||
{ | ||
js.w(")").unindent | ||
} | ||
} | ||
else | ||
{ | ||
// this closure uses non-JS types. Write a closure that documents this fact | ||
js.wl("() => {") | ||
js.wl(" // Cannot write closure. Signature uses non-JS types: ${ce.signature}") | ||
js.wl(" throw sys.UnsupportedErr.make('Closure uses non-JS types: ' + ${ce.signature.toStr.toCode});") | ||
js.w("}") | ||
} | ||
} | ||
|
||
** Write the unique closure specification fields for this pod (JsPod) | ||
override Void write() | ||
{ | ||
varToFunc.each |MethodDef func, Str var| | ||
{ | ||
loc := func.loc | ||
js.w("const ${var} = [${qnameToJs(func.ret)}.type\$,") | ||
js.w("sys.List.make(sys.Param.type\$, [") | ||
func.params.each |p,i| | ||
{ | ||
if (i>0) js.w(",") | ||
js.w("new sys.Param(${p.name.toCode}, ${p.paramType.signature.toCode}, ${p.hasDefault})") | ||
} | ||
js.w("])") | ||
.w("];").nl | ||
} | ||
js.nl | ||
} | ||
|
||
private Str mapFuncSpec(ClosureExpr ce) | ||
{ | ||
var := specKeyToVar.getOrAdd(specKey(ce)) |->Str| | ||
{ | ||
// "${ce.enclosingType.pod}.__clos${plugin.nextUid}" | ||
"__clos${plugin.nextUid}" | ||
} | ||
varToFunc[var] = ce.doCall | ||
return var | ||
} | ||
|
||
private static Str specKey(ClosureExpr ce) | ||
{ | ||
MethodDef func := ce.doCall | ||
buf := StrBuf() | ||
func.params.each |p| | ||
{ | ||
buf.add("${p.name}-${p.paramType.signature}-${p.hasDefault},") | ||
} | ||
buf.add("${func.ret.signature}") | ||
return buf.toStr | ||
} | ||
|
||
** Func spec key to field variable name | ||
private Str:Str specKeyToVar := [:] | ||
|
||
** Func spec field variable name to prototype function (for params and return type) | ||
private Str:MethodDef varToFunc := [:] { ordered = true } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters