Skip to content

Instantly share code, notes, and snippets.

@dobesv
Created March 2, 2012 16:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dobesv/1959419 to your computer and use it in GitHub Desktop.
Save dobesv/1959419 to your computer and use it in GitHub Desktop.
Changes I made to the Fantom compiler module to make it easier to create my DSL
using compiler
class CoroutineDslPlugin : DslPlugin
{
new make(Compiler c) : super(c) {}
override Expr compile(DslExpr dsl)
{
src := dsl.src
loc := dsl.srcLoc
unit := CompilationUnit(loc, pod)
tokenizer := Tokenizer(compiler, loc, "{ $src }", compiler.input.includeDoc)
unit.tokens = tokenizer.tokenize
// Clone imports from the current unit
parentUnit := units.find |u| { return u.loc.file == loc.file }
unit.importedTypes = parentUnit.importedTypes
tmpClassDef := unit.types.first
//unit.types.add(tmpClassDef);
parser := Parser(compiler, unit, compiler.closures) {
curType = dsl.enclosingType
curSlot = dsl.enclosingSlot
curClosure = dsl.enclosingClosure
closureCount = this.compiler.closures.size
}
try {
FuncType signature := FuncType([,], [,], ns.resolveType("sys::Void"))
ClosureExpr closure := parser.closure(loc, signature)
// TODO Here is where we would transform it to support
InitClosures(compiler).process(closure)
Normalize(compiler).visitTypeDef(closure.cls)
closure.cls.dump
return closure
} catch (sys::NullErr e)
{
echo(e)
e.trace
throw err("Null pointer exception during parse!", loc);
}
}
}
using sys::Test
using coroutine
class CoroutineTest : Test
{
Void testSimpleEcho() {
x := Coroutine<| echo("This is a test!") |>
x()
}
Void testSimpleEchoReturn() {
// Just making sure we haven't messed up the return statement support somehow
x := Coroutine<| echo("This is a test!"); return |>
x()
}
Void testEnclosedVar1() {
i := 1
x := Coroutine<| echo("$i"); i++ |>
x()
x()
}
Void testEnclosedVar2() {
i := 1
x := Coroutine<| i++ |>
x()
x()
echo("x == $x")
}
}
diff --git a/src/compiler/fan/ast/Expr.fan b/src/compiler/fan/ast/Expr.fan
--- a/src/compiler/fan/ast/Expr.fan
+++ b/src/compiler/fan/ast/Expr.fan
@@ -1590,12 +1590,16 @@
**
class DslExpr : Expr
{
- new make(Loc loc, CType anchorType, Loc srcLoc, Str src)
+ new make(Loc loc, CType anchorType, Loc srcLoc, TypeDef enclosingType,
+ SlotDef enclosingSlot, ClosureExpr? enclosingClosure, Str src)
: super(loc, ExprId.dsl)
{
this.anchorType = anchorType
this.src = src
this.srcLoc = srcLoc
+ this.enclosingType = enclosingType;
+ this.enclosingSlot = enclosingSlot;
+ this.enclosingClosure = enclosingClosure;
}
override Str toStr()
@@ -1613,6 +1617,9 @@
Loc srcLoc // location of first char of src
Int leadingTabs // number of leading tabs on original Fantom line
Int leadingSpaces // number of leading non-tab chars on original Fantom line
+ TypeDef enclosingType // enclosing class
+ SlotDef enclosingSlot // enclosing method or field initializer
+ ClosureExpr? enclosingClosure // if inside a closure
}
**************************************************************************
diff --git a/src/compiler/fan/parser/Parser.fan b/src/compiler/fan/parser/Parser.fan
--- a/src/compiler/fan/parser/Parser.fan
+++ b/src/compiler/fan/parser/Parser.fan
@@ -1581,7 +1581,7 @@
{
srcLoc := Loc(cur.file, cur.line, cur.col+2)
dslVal := cur as TokenValDsl
- return DslExpr(loc, ctype, srcLoc, consume.val)
+ return DslExpr(loc, ctype, srcLoc, curType, curSlot, curClosure, consume.val)
{
leadingTabs = dslVal.leadingTabs
leadingSpaces = dslVal.leadingSpaces
@@ -1997,7 +1997,7 @@
**
** Parse body of closure expression and return ClosureExpr.
**
- private ClosureExpr closure(Loc loc, FuncType funcType)
+ public ClosureExpr closure(Loc loc, FuncType funcType)
{
if (curSlot == null) throw err("Unexpected closure")
@@ -2426,10 +2426,10 @@
private TokenVal? peek // next token
private Token? peekt // next token type
private Bool inFieldInit // are we currently in a field initializer
- private TypeDef? curType // current TypeDef scope
- private SlotDef? curSlot // current SlotDef scope
- private ClosureExpr? curClosure // current ClosureExpr if inside closure
- private Int? closureCount // number of closures parsed inside curSlot
+ TypeDef? curType // current TypeDef scope
+ SlotDef? curSlot // current SlotDef scope
+ ClosureExpr? curClosure // current ClosureExpr if inside closure
+ Int? closureCount // number of closures parsed inside curSlot
private ClosureExpr[] closures // list of all closures parsed
}
\ No newline at end of file
diff --git a/src/compiler/fan/steps/InitClosures.fan b/src/compiler/fan/steps/InitClosures.fan
--- a/src/compiler/fan/steps/InitClosures.fan
+++ b/src/compiler/fan/steps/InitClosures.fan
@@ -39,7 +39,7 @@
// Process
//////////////////////////////////////////////////////////////////////////
- private Void process(ClosureExpr c)
+ Void process(ClosureExpr c)
{
// class Class$Method$Num : |A,B..->R|
// {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment