pass typed data back and forth with #extern. close #17
This commit is contained in:
@@ -466,19 +466,37 @@ class Helpers {
|
||||
// Return convenient functions for succinctly making new ReaderExps that link back to an original exp's
|
||||
// position in source code
|
||||
public static function expBuilder(posRef:ReaderExp) {
|
||||
function _symbol(?name:String) {
|
||||
return Prelude.symbol(name).withPosOf(posRef);
|
||||
}
|
||||
function call(func:ReaderExp, args:Array<ReaderExp>) {
|
||||
return CallExp(func, args).withPosOf(posRef);
|
||||
}
|
||||
function callSymbol(symbol:String, args:Array<ReaderExp>) {
|
||||
return call(_symbol(symbol), args);
|
||||
}
|
||||
function field(f:String, exp:ReaderExp) {
|
||||
return FieldExp(f, exp).withPosOf(posRef);
|
||||
}
|
||||
function list(exps:Array<ReaderExp>) {
|
||||
return ListExp(exps).withPosOf(posRef);
|
||||
}
|
||||
return {
|
||||
call: (func:ReaderExp, args:Array<ReaderExp>) -> CallExp(func, args).withPosOf(posRef),
|
||||
callSymbol: (symbol:String, args:Array<ReaderExp>) -> CallExp(Symbol(symbol).withPosOf(posRef), args).withPosOf(posRef),
|
||||
call: call,
|
||||
callSymbol: callSymbol,
|
||||
callField: (fieldName:String, callOn:ReaderExp, args:Array<ReaderExp>) -> call(field(fieldName, callOn), args),
|
||||
print: (arg:ReaderExp) -> CallExp(Symbol("print").withPosOf(posRef), [arg]).withPosOf(posRef),
|
||||
list: (exps:Array<ReaderExp>) -> ListExp(exps).withPosOf(posRef),
|
||||
the: (type:ReaderExp, value:ReaderExp) -> callSymbol("the", [type, value]),
|
||||
list: list,
|
||||
str: (s:String) -> StrExp(s).withPosOf(posRef),
|
||||
symbol: (?name:String) -> Prelude.symbol(name).withPosOf(posRef),
|
||||
symbol: _symbol,
|
||||
raw: (code:String) -> RawHaxe(code).withPosOf(posRef),
|
||||
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
|
||||
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
|
||||
field: (f:String, exp:ReaderExp) -> FieldExp(f, exp).withPosOf(posRef),
|
||||
field: field,
|
||||
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
|
||||
begin: (exps:Array<ReaderExp>) -> CallExp(Symbol("begin").withPosOf(posRef), exps).withPosOf(posRef),
|
||||
begin: (exps:Array<ReaderExp>) -> callSymbol("begin", exps),
|
||||
let: (bindings:Array<ReaderExp>, body:Array<ReaderExp>) -> callSymbol("let", [list(bindings)].concat(body)),
|
||||
none: () -> None.withPosOf(posRef)
|
||||
};
|
||||
}
|
||||
|
@@ -809,25 +809,49 @@ class Macros {
|
||||
{};
|
||||
}
|
||||
|
||||
trace(compileArgs);
|
||||
trace(bindingListExp);
|
||||
// TODO generate tink_json writers and parsers for this
|
||||
|
||||
var b = wholeExp.expBuilder();
|
||||
|
||||
// TODO generate tink_json writers and parsers for this
|
||||
var bindingList = bindingListExp.bindingList("#extern", true);
|
||||
|
||||
var idx = 0;
|
||||
var stringifyExpList = [];
|
||||
var parseBindingList = [];
|
||||
while (idx < bindingList.length) {
|
||||
var type = "";
|
||||
var untypedName = switch (bindingList[idx].def) {
|
||||
case TypedExp(_type, symbol = {pos: _, def: Symbol(name)}):
|
||||
type = _type;
|
||||
symbol;
|
||||
default: throw CompileError.fromExp(bindingList[idx], "name in #extern binding list must be a typed symbol");
|
||||
};
|
||||
switch (bindingList[idx + 1].def) {
|
||||
// _ in the value position of the #extern binding list will reuse the name as the value
|
||||
case Symbol("_"):
|
||||
bindingList[idx + 1] = untypedName;
|
||||
default:
|
||||
}
|
||||
stringifyExpList.push(b.callSymbol("tink.Json.stringify", [b.the(b.symbol(type), bindingList[idx + 1])]));
|
||||
parseBindingList.push(bindingList[idx]);
|
||||
parseBindingList.push(b.callSymbol("tink.Json.parse", [b.callField("readLine", b.callSymbol("Sys.stdin", []), [])]));
|
||||
idx += 2;
|
||||
}
|
||||
|
||||
var externExps = [
|
||||
b.print(
|
||||
b.callSymbol("tink.Json.stringify", [
|
||||
b.callSymbol("the", [
|
||||
bodyType, b.begin(exps)
|
||||
])
|
||||
b.the(bodyType, if (bindingList.length > 0) {
|
||||
b.let(parseBindingList, exps);
|
||||
} else {
|
||||
b.begin(exps);
|
||||
})
|
||||
]))
|
||||
];
|
||||
b.callSymbol("the", [
|
||||
b.the(
|
||||
bodyType,
|
||||
b.callSymbol("tink.Json.parse", [
|
||||
b.call(b.raw(CompilerTools.compileToScript(externExps, langArg, compileArgs).toString()), [])
|
||||
])
|
||||
]);
|
||||
b.call(b.raw(CompilerTools.compileToScript(externExps, langArg, compileArgs).toString()), [b.list(stringifyExpList)])
|
||||
]));
|
||||
};
|
||||
|
||||
return macros;
|
||||
|
@@ -7,6 +7,7 @@ import kiss.Prelude;
|
||||
|
||||
@:build(kiss.Kiss.build())
|
||||
class ExternTestCase extends Test {
|
||||
#if (sys || hxnodejs)
|
||||
function testExternPython() {
|
||||
_testExternPython();
|
||||
}
|
||||
@@ -14,4 +15,5 @@ class ExternTestCase extends Test {
|
||||
function testExternJavaScript() {
|
||||
_testExternJavaScript();
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
@@ -1,13 +1,10 @@
|
||||
(function _testExternPython []
|
||||
(Assert.isTrue
|
||||
(#extern Bool python []
|
||||
(#if python
|
||||
true
|
||||
false))))
|
||||
(#extern Bool python [:String passingString "Hello python!"]
|
||||
(python.NativeStringTools.startswith passingString "Hello"))))
|
||||
|
||||
(function _testExternJavaScript []
|
||||
(Assert.isTrue
|
||||
(#extern Bool js []
|
||||
(#if js
|
||||
true
|
||||
false))))
|
||||
(Assert.equals 18
|
||||
(let [jsToEval "5+6+7"]
|
||||
(#extern Int js [:String jsToEval _]
|
||||
(js.Lib.eval jsToEval)))))
|
Reference in New Issue
Block a user