pass typed data back and forth with #extern. close #17

This commit is contained in:
2021-07-26 19:55:28 -06:00
parent 700a4de08b
commit fba736f4f2
4 changed files with 67 additions and 26 deletions

View File

@@ -466,19 +466,37 @@ class Helpers {
// Return convenient functions for succinctly making new ReaderExps that link back to an original exp's // Return convenient functions for succinctly making new ReaderExps that link back to an original exp's
// position in source code // position in source code
public static function expBuilder(posRef:ReaderExp) { 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 { return {
call: (func:ReaderExp, args:Array<ReaderExp>) -> CallExp(func, args).withPosOf(posRef), call: call,
callSymbol: (symbol:String, args:Array<ReaderExp>) -> CallExp(Symbol(symbol).withPosOf(posRef), args).withPosOf(posRef), 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), 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), str: (s:String) -> StrExp(s).withPosOf(posRef),
symbol: (?name:String) -> Prelude.symbol(name).withPosOf(posRef), symbol: _symbol,
raw: (code:String) -> RawHaxe(code).withPosOf(posRef), raw: (code:String) -> RawHaxe(code).withPosOf(posRef),
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef), typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
meta: (m:String, exp:ReaderExp) -> MetaExp(m, 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), 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) none: () -> None.withPosOf(posRef)
}; };
} }

View File

@@ -809,25 +809,49 @@ class Macros {
{}; {};
} }
trace(compileArgs);
trace(bindingListExp);
// TODO generate tink_json writers and parsers for this
var b = wholeExp.expBuilder(); 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 = [ var externExps = [
b.print( b.print(
b.callSymbol("tink.Json.stringify", [ b.callSymbol("tink.Json.stringify", [
b.callSymbol("the", [ b.the(bodyType, if (bindingList.length > 0) {
bodyType, b.begin(exps) b.let(parseBindingList, exps);
]) } else {
b.begin(exps);
})
])) ]))
]; ];
b.callSymbol("the", [ b.the(
bodyType, bodyType,
b.callSymbol("tink.Json.parse", [ 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; return macros;

View File

@@ -7,6 +7,7 @@ import kiss.Prelude;
@:build(kiss.Kiss.build()) @:build(kiss.Kiss.build())
class ExternTestCase extends Test { class ExternTestCase extends Test {
#if (sys || hxnodejs)
function testExternPython() { function testExternPython() {
_testExternPython(); _testExternPython();
} }
@@ -14,4 +15,5 @@ class ExternTestCase extends Test {
function testExternJavaScript() { function testExternJavaScript() {
_testExternJavaScript(); _testExternJavaScript();
} }
#end
} }

View File

@@ -1,13 +1,10 @@
(function _testExternPython [] (function _testExternPython []
(Assert.isTrue (Assert.isTrue
(#extern Bool python [] (#extern Bool python [:String passingString "Hello python!"]
(#if python (python.NativeStringTools.startswith passingString "Hello"))))
true
false))))
(function _testExternJavaScript [] (function _testExternJavaScript []
(Assert.isTrue (Assert.equals 18
(#extern Bool js [] (let [jsToEval "5+6+7"]
(#if js (#extern Int js [:String jsToEval _]
true (js.Lib.eval jsToEval)))))
false))))