module lang::flybytes::demo::protol::Compiler
rascal-0.40.17
flybytes-0.2.8
Usage
import lang::flybytes::demo::protol::Compiler;
Source code
http://github.com/usethesource/flybytes/blob/main/src/lang/flybytes/demo/protol/Compiler.rsc
Dependencies
import lang::flybytes::Syntax;
import lang::flybytes::Compiler;
import lang::flybytes::demo::protol::Syntax;
import lang::flybytes::api::Object;
import lang::flybytes::api::System;
import ParseTree;
import String;
function testProtol
void testProtol() {
tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/fact.protol|).top;
compileProgram(tree, "ProtolFactorial", |project://flybytes/generated|);
tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/inheritance.protol|).top;
compileProgram(tree, "ProtolInheritance", |project://flybytes/generated|);
tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/missing.protol|).top;
compileProgram(tree, "ProtolMissing", |project://flybytes/generated|);
tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/fields.protol|).top;
compileProgram(tree, "ProtolFields", |project://flybytes/generated|);
}
function protoClass
str protoClass() {
res = "Proto_<program>_<prototypes>";
prototypes += 1;
return res;
}
function compileProgram
void compileProgram(Program p, str name, loc binFolder) {
prototypes = 0;
program = name;
classes = compile(p, name);
for (cl <- classes) {
compileClass(cl, binFolder + "<cl.\type.name>.class", version=v1_8(), debugMode=true);
}
}
function getInt
Exp getInt(Exp rec) = invokeDynamic(bootstrap(Prototype, "bootstrap", []), Prototype_getInteger, [rec]);
function getArray
Exp getArray(Exp rec) = invokeDynamic(bootstrap(Prototype, "bootstrap", []), Prototype_getArray, [rec]);
data Type
data Type
= prototype(str name, list[Method] methods, list[Field] fields)
;
function compile
list[Class] compile(Program p, str name) {
progClass = class(object(name),
methods=[
main("args", [*compileAll(p.commands), \return()])[src=p@\loc]
]
)[src=p@\loc];
allClasses = [removePrototypeClasses(progClass), *extractPrototypeClasses(progClass)];
return declareVariables(allClasses);
}
function compileAll
list[Stat] compileAll(Command* commands) = [compile(c)[src=c@\loc] | c <- commands];
function compile
Stat compile((Command) `<Id id> = <Expr v>;`)
= store("<id>", compile(v));
Stat compile((Command) `<Expr obj>.<Id name> = <Expr v>;`)
= \do(invokeDynamic(bootstrap(Prototype, "bootstrap", []), methodDesc(Prototype, "$set_<name>", [Prototype]), [compile(obj), compile(v)]));
function PROTO
Exp PROTO() = getStatic(Prototype, Prototype, "PROTO");
function compile
Stat compile((Command) `<Expr array>[<Expr index>] = <Expr v>;`)
= astore(compile(array), getInt(compile(index)), compile(v));
Stat compile((Command) `if(<Expr cond >) { <Command* thenPart> } else { <Command* elsePart> }`)
= \if(compile(cond), compileAll(thenPart), compileAll(elsePart));
Stat compile((Command) `while(<Expr cond>) { <Command* body> }`)
= \while(compile(cond), compileAll(body));
Stat compile((Command) `<Expr e>;`) = \do(compile(e));
Stat compile((Command) `return <Expr e>;`) = \return(compile(e));
Stat compile((Command) `print <Expr e>;`) = stdout(compile(e));
Exp compile(e:(Expr) `this`) = load("this", src=e@\loc);
Exp compile((Expr) `<Expr rec>.<Id name>(<{Expr ","}* args>)`)
= invokeDynamic(bootstrap(Prototype, "bootstrap", []), methodDesc(Prototype, "<name>", [Prototype]/*receiver*/ + [Prototype | _ <- args] ), [compile(rec), *compileList(args) ])[src=name@\loc];
function compileList
list[Exp] compileList({Expr ","}* args) = [compile(a)[src=a@\loc] | a <- args];
function compile
Exp compile(x:(Expr) `[<{Expr ","}* elems>]`)
= new(Arr, [array(Prototype)], [newInitArray(array(Prototype), [compile(e) | e <- elems])])[src=x@\loc];
Exp compile((Expr) `<Expr receiver>.<Id name>`)
= invokeDynamic(bootstrap(Prototype, "bootstrap", []), methodDesc(Prototype, "$get_<name>", []), [compile(receiver)])[src=name@\loc];
Exp compile(x:(Expr) `new`) = new(Prototype, [Prototype], [PROTO()])[src=x@\loc];
Exp compile(x:(Expr) `new <Expr p>`) = new(Prototype, [Prototype], [compile(p)])[src=x@\loc];
Exp compile(x:(Expr) `new { <Definition* defs> }`)
= new(prototype(protoClass(), methods(defs), fields(defs)), [Prototype], [PROTO()])[src=x@\loc];
Exp compile(x:(Expr) `new <Expr p> { <Definition* defs> }`)
= new(prototype(protoClass(), methods(defs), fields(defs)), [Prototype], [compile(p)])[src=x@\loc];
Exp compile((Expr) `(<Expr e>)`) = compile(e);
Exp compile(x:(Expr) `<Id i>`) = load("<i>", src=x@\loc);
Exp compile(x:(Expr) `<Int i>`) = newInt(iconst(toInt("<i>")))[src=x@\loc];
Exp compile(x:(Expr) `<String s>`) = new(Str, [string()], [sconst("<s>"[1..-1])])[src=x@\loc];
Exp compile(x:(Expr) `<Expr a>[<Expr index>]`)
= aload(getArray(compile(a)), getInt(compile(index)))[src=x@\loc];
function newInt
Exp newInt(Exp e) = new(Int, [integer()], [e]);
function compile
Exp compile(Expr l, Expr r, Exp (Exp, Exp) op)
= op(getInt(compile(l)), getInt(compile(r)));
Exp compile(x:(Expr) `<Expr l> * <Expr r>`)
= newInt(compile(l, r, mul)[src=x@\loc]);
Exp compile(x:(Expr) `<Expr l> / <Expr r>`)
= newInt(compile(l, r, div)[src=x@\loc]);
Exp compile(x:(Expr) `<Expr l> + <Expr r>`)
= newInt(compile(l, r, add)[src=x@\loc]);
Exp compile(x:(Expr) `<Expr l> - <Expr r>`)
= newInt(compile(l, r, sub)[src=x@\loc]);
Exp compile(x:(Expr) `<Expr l> == <Expr r>`)
= equals(compile(l), compile(r)[src=x@\loc]);
Exp compile(x:(Expr) `<Expr l> != <Expr r>`)
= neg(equals(compile(l), compile(r))[src=x@\loc]);
Exp compile(x:(Expr) `<Expr l> \<\< <Expr r>`)
= invokeVirtual(Prototype, compile(l), methodDesc(Prototype, "concat", [Prototype]), [compile(r)])[src=x@\loc];
Exp compile(x:(Expr) `<Expr l> \<= <Expr r>`)
= compile(l, r, le)[src=x@\loc];
Exp compile(x:(Expr) `<Expr l> \< <Expr r>`)
= compile(l, r, lt)[src=x@\loc];
Exp compile(x:(Expr) `<Expr l> \> <Expr r>`)
= compile(l, r, gt)[src=x@\loc];
Exp compile(x:(Expr) `<Expr l> \>= <Expr r>`)
= compile(l, r, ge)[src=x@\loc];
function methods
list[Method] methods(Definition* defs)
= [ method("<name>", args, commands)[src=name@\loc]
| (Definition) `<Id name>(<{Id ","}* args>) { <Command* commands> }` <- defs]
+
[ method("missing", missingArgs(name, args), commands)[src=d@\loc]
| d:(Definition) `missing(<Id name>, <Id args>) { <Command* commands> }` <- defs]
+
[ getter("<name>")[src=name@\loc], setter("<name>")[src=name@\loc] | (Definition) `<Id name> = <Expr _>` <- defs]
;
function getter
Method getter(str name)
= method(\public(), Prototype, "$get_<name>", [], [\return(getField(Prototype, "<name>"))]);
function setter
Method setter(str name)
= method(\public(), \void(), "$set_<name>", [var(Prototype, "a")], [putField(Prototype, "<name>", load("a")), \return()]);
function missingArgs
{Id ","}* missingArgs(Id name, Id args)
= ((Definition) `dummy(<Id name>, <Id args>) { }`).args;
function fields
list[Field] fields(Definition* defs)
= [ field("<name>", val)[src=name@\loc] | (Definition) `<Id name> = <Expr val>` <- defs];
function method
Method method(str name, {Id ","}* args, Command* commands)
= method(\public(), Prototype, name, [var(Prototype, "<a>") | a <- args], compileAll(commands));
function field
Field field(str name, Expr val)
= field(Prototype, name, init=compile(val), modifiers={\public()});
function declareVariables
&T declareVariables(&T classes)
= visit(classes) {
case method(Signature desc, list[Formal] formals, list[Stat] block, modifiers=m) =>
method(desc, formals, [*ds, *block], modifiers=m)
when
// transform assignments to declarations and remove duplicates:
set[Stat] ds := { decl(Prototype, name) | /store(str name, _) := block}
};
function removePrototypeClasses
Class removePrototypeClasses(Class main) = visit(main) {
case prototype(n, _, _) => object(n)
};
function extractPrototypeClasses
list[Class] extractPrototypeClasses(Class main)
= [ class(object(name),
super=Prototype,
methods=[*ms,
// public Class(Prototype proto) { super(proto); }
constructor(\public(), [var(Prototype, "proto")], [
invokeSuper([Prototype], [load("proto")]),
\return()
])
],
fields=fs
)[src=main.src]
| /prototype(str name, ms, fs) := main];