34 Commits

Author SHA1 Message Date
8792a36dfe implement field access
Some checks failed
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 1m40s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Failing after 1m46s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 2m16s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Failing after 3m10s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 2m58s
2025-09-12 20:27:32 -05:00
4670a8bd4e interp special forms map, if
Some checks failed
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Failing after 1m56s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Successful in 2m28s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 2m34s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 3m28s
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 3m39s
2025-09-12 19:52:13 -05:00
722e475925 scaffold KissInterp2
All checks were successful
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 1m38s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 1m44s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Successful in 1m51s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Successful in 2m44s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 4m29s
2025-09-12 17:11:07 -05:00
84b09821f2 Revert "disable an annoying old type check syntax"
All checks were successful
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Successful in 2m5s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 1m48s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Successful in 2m2s
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 3m11s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 3m48s
This reverts commit 0e02c6c910.
2025-09-09 13:59:12 -05:00
c88d7a44f8 find libpath for lix git library
All checks were successful
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Successful in 47s
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 1m12s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Successful in 1m9s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 1m24s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 1m52s
2025-09-09 13:00:31 -05:00
4da446c0f7 get tink_macro from gitea
All checks were successful
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 2m52s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Successful in 3m36s
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 3m57s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Successful in 3m39s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 4m30s
2025-09-09 12:43:56 -05:00
f7f8ec8690 Make action run on gitea
All checks were successful
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Successful in 42s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Successful in 49s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Successful in 1m54s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Successful in 1m37s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Successful in 2m3s
2025-09-09 09:58:50 -05:00
033b424b20 disable lua jobs for now
Some checks failed
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Failing after 1m44s
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Failing after 1m41s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Failing after 1m38s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Failing after 1m45s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Failing after 1m42s
2025-09-08 15:45:49 -05:00
929ae557ed allow :Null on lambda and arrow lambda 2025-08-08 12:10:11 -05:00
e1bd5eff02 default value arg for extractOpt 2025-08-08 10:20:32 -05:00
f06200c1a1 special case :Null return type on functions. fix #18 2025-08-08 10:20:07 -05:00
ca91f4a57d Stream.takeLinesAsStreamWhile 2025-08-07 18:18:38 -05:00
62c8396ea5 Stream.peekLine() 2025-08-07 18:18:25 -05:00
6085697914 extractOpt 2025-08-07 18:18:10 -05:00
c0ab63cdb0 Fix bug for &opt args in defMacro 2025-07-30 17:20:14 -05:00
bca1dfd8c6 try to fix fossilBuild on github actions 2025-07-30 14:18:12 -05:00
926948498e Fix redefineWithObjectArgs changing access of original 2025-07-29 16:40:25 -05:00
1d4219a87d fix form example for localVar 2025-06-16 15:16:37 -05:00
e7b4cb0590 shellExecute print the error 2025-06-16 10:45:06 -05:00
07a09f8f98 shellExecute() return output 2025-06-16 10:10:07 -05:00
a9129952f3 new-express-project add a systemd unit 2025-05-27 16:44:01 -05:00
5cbd17bf55 redefineWithObjectArgs allow changing access public/private 2025-03-12 11:01:14 -05:00
67cdf396b5 Don't warn that ++, -- exps are unused 2025-03-12 09:44:57 -05:00
50845be826 try install libreadline-dev for lua CI 2025-02-13 09:18:47 -06:00
bb18997606 refactor ExpBuilder to be a class, not anonymous object 2025-02-13 09:15:41 -06:00
fb34feb610 pass kissFile to macro bodies 2025-02-03 14:09:58 -06:00
91b1fc7b32 print awaitLet error message 2025-02-03 13:01:07 -06:00
404c15d684 compile-guard some ExpBuilder functions 2025-02-03 10:43:42 -06:00
b7722a6dbb removeTypeAnnotations support listeater expressions 2025-02-03 10:37:17 -06:00
35b1dffc09 fix new-firefox-project 2025-02-02 17:59:54 -06:00
936526f83d new-express-project fail before taking input 2025-02-02 17:52:46 -06:00
7e1e64e5b3 fix new-express-project 2025-02-02 17:49:49 -06:00
95f9d93069 kiss main find libs relative to kiss 2025-02-02 17:39:35 -06:00
247b32838d fix new-project command 2025-01-25 15:02:36 -06:00
30 changed files with 603 additions and 191 deletions

View File

@@ -18,12 +18,12 @@ jobs:
- js
- nodejs
- py
- "lua 5.1"
- "lua 5.2"
- "lua 5.3"
- "lua 5.4"
- "luajit 2.0"
- "luajit 2.1"
# - "lua 5.1"
# - "lua 5.2"
# - "lua 5.3"
# - "lua 5.4"
# - "luajit 2.0"
# - "luajit 2.1"
runs-on: ${{ matrix.os }}
env:
CI_OS_NAME: ${{ matrix.os }}
@@ -33,13 +33,12 @@ jobs:
# Set up Kiss runtimes:
# nodejs
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
if: matrix.test-target == 'nodejs'
# - uses: actions/setup-node@v3
# with:
# node-version: ${{ matrix.node-version }}
# lix
- uses: lix-pm/setup-lix@master
- uses: https://k7izh9.gitea.cloud/kiss-lang/setup-lix@1.0.2
with:
lix-version: 15.12.0
@@ -50,6 +49,8 @@ jobs:
if: matrix.test-target == 'py'
# lua
- run: sudo apt-get install libreadline-dev
if: contains(matrix.test-target, 'lua')
- run: pip install --user hererocks && hererocks env --$LUA -rlatest && source env/bin/activate && ./build-scripts/lua/install-deps.sh
if: contains(matrix.test-target, 'lua')

View File

@@ -4,5 +4,4 @@
-lib tink_macro
-lib tink_syntaxhub
-lib haxe-strings
-cp src
--run kiss.Main

View File

@@ -0,0 +1,7 @@
-lib kiss
-lib vscode
-lib hxnodejs
-lib re-flex
-cp /Users/nat/repos/kiss-vscode-api/src/
-D kiss-vscode-api=0.0.0
--macro Sys.println("haxe_libraries/kiss-vscode-api.hxml:6: [Warning] Using dev version of library kiss-vscode-api")

View File

@@ -1,4 +1,4 @@
# @install: lix --silent download "gh://github.com/kiss-lang/tink_macro#8b60a484b1141d1176b34ba3af9ac65b499079ff" into tink_macro/1.0.3/github/8b60a484b1141d1176b34ba3af9ac65b499079ff
# @install: lix --silent download "git:https://k7izh9.gitea.cloud/kiss-lang/tink_macro#8b60a484b1141d1176b34ba3af9ac65b499079ff" into tink_macro/1.0.3/git/8b60a484b1141d1176b34ba3af9ac65b499079ff
-lib tink_core
-cp ${HAXE_LIBCACHE}/tink_macro/1.0.3/github/8b60a484b1141d1176b34ba3af9ac65b499079ff/src
-cp ${HAXE_LIBCACHE}/tink_macro/1.0.3/git/8b60a484b1141d1176b34ba3af9ac65b499079ff/src
-D tink_macro=1.0.3

View File

@@ -5,133 +5,164 @@ using kiss.Helpers;
using kiss.Reader;
using kiss.ExpBuilder;
// Has convenient functions for succinctly making new ReaderExps that link back to an original exp's
// position in source code
class ExpBuilder {
// Return convenient functions for succinctly making new ReaderExps that link back to an original exp's
// position in source code
var posRef:ReaderExp;
function new(posRef:ReaderExp) {
this.posRef = posRef;
}
public static function expBuilder(posRef:ReaderExp) {
function _symbol(?name:String) {
return Prelude.symbol(name).withPosOf(posRef);
return new ExpBuilder(posRef);
}
public function symbol(?name:String) {
return Prelude.symbol(name).withPosOf(posRef);
}
public function call(func:ReaderExp, args:Array<ReaderExp>) {
return CallExp(func, args).withPosOf(posRef);
}
public function callSymbol(_symbol:String, args:Array<ReaderExp>) {
return call(symbol(_symbol), args);
}
public function field(f:String, exp:ReaderExp, ?safe:Bool) {
return FieldExp(f, exp, safe != null && safe).withPosOf(posRef);
}
public function list(exps:Array<ReaderExp>) {
return ListExp(exps).withPosOf(posRef);
}
public function objectWith (bindings:Array<ReaderExp>, captures:Array<ReaderExp>) {
return callSymbol("objectWith", [list(bindings)].concat(captures));
}
public function str(s:String) {
return StrExp(s).withPosOf(posRef);
}
public function raw(code:String) {
return RawHaxe(code).withPosOf(posRef);
}
public function int(v:Int) {
return symbol(Std.string(v));
}
public function float(v:Float) {
return symbol(Std.string(v));
}
public function let(bindings:Array<ReaderExp>, body:Array<ReaderExp>) {
return callSymbol("let", [list(bindings)].concat(body));
}
public function _if(condition:ReaderExp, then:ReaderExp, ?_else:ReaderExp) {
var args = [condition, then];
if (_else != null)
args.push(_else);
return callSymbol("if", args);
}
#if (sys || hxnodejs)
public function throwAssertOrNeverError(messageExp:ReaderExp) {
var failureError = KissError.fromExp(posRef, "").toString(AssertionFail);
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
return callSymbol("throw", [
callSymbol("kiss.Prelude.runtimeInsertAssertionMessage", [messageExp, str(failureError), int(colonsInPrefix)])
]);
}
#end
function _whenUnless(which:String, condition:ReaderExp, body:Array<ReaderExp>) {
return callSymbol(which, [condition].concat(body));
}
public function when(condition:ReaderExp, body:Array<ReaderExp>) {
return _whenUnless("when", condition, body);
}
public function unless(condition:ReaderExp, body:Array<ReaderExp>) {
return _whenUnless("unless", condition, body);
}
public function callField(fieldName:String, callOn:ReaderExp, args:Array<ReaderExp>) {
return call(field(fieldName, callOn), args);
}
public function print(arg:ReaderExp) {
return CallExp(Symbol("print").withPosOf(posRef), [arg]).withPosOf(posRef);
}
public function the(type:ReaderExp, value:ReaderExp) {
return callSymbol("the", [type, value]);
}
public function not(exp:ReaderExp) {
return callSymbol("not", [exp]);
}
public function typed(path:String, exp:ReaderExp) {
return TypedExp(path, exp).withPosOf(posRef);
}
public function meta(m:String, exp:ReaderExp) {
return MetaExp(m, exp).withPosOf(posRef);
}
public function keyValue(key:ReaderExp, value:ReaderExp) {
return KeyValueExp(key, value).withPosOf(posRef);
}
public function begin(exps:Array<ReaderExp>) {
return callSymbol("begin", exps);
}
public function set(v:ReaderExp, value:ReaderExp) {
return callSymbol("set", [v, value]);
}
public function expFromDef(def:ReaderExpDef) {
return def.withPosOf(posRef);
}
#if (sys || hxnodejs)
// Only use within assertion macros
public function throwAssertionError() {
var usage = "throwAssertionError can only be used in a builder of an assertion macro";
var exps = switch (posRef.def) {
case CallExp(_, exps):
exps;
default:
throw KissError.fromExp(symbol("throwAssertionError"), usage);
}
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, ?safe:Bool) {
return FieldExp(f, exp, safe != null && safe).withPosOf(posRef);
}
function list(exps:Array<ReaderExp>) {
return ListExp(exps).withPosOf(posRef);
}
function objectWith (bindings:Array<ReaderExp>, captures:Array<ReaderExp>) {
return callSymbol("objectWith", [list(bindings)].concat(captures));
}
function str(s:String) {
return StrExp(s).withPosOf(posRef);
}
function raw(code:String) {
return RawHaxe(code).withPosOf(posRef);
}
function int(v:Int) {
return _symbol(Std.string(v));
}
function float(v:Float) {
return _symbol(Std.string(v));
}
function let(bindings:Array<ReaderExp>, body:Array<ReaderExp>) {
return callSymbol("let", [list(bindings)].concat(body));
}
function _if(condition:ReaderExp, then:ReaderExp, ?_else:ReaderExp) {
var args = [condition, then];
if (_else != null)
args.push(_else);
return callSymbol("if", args);
}
function throwAssertOrNeverError(messageExp:ReaderExp) {
var failureError = KissError.fromExp(posRef, "").toString(AssertionFail);
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
return callSymbol("throw", [
callSymbol("kiss.Prelude.runtimeInsertAssertionMessage", [messageExp, str(failureError), int(colonsInPrefix)])
]);
}
function whenUnless(which:String, condition:ReaderExp, body:Array<ReaderExp>) {
return callSymbol(which, [condition].concat(body));
}
return {
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),
the: (type:ReaderExp, value:ReaderExp) -> callSymbol("the", [type, value]),
not: (exp:ReaderExp) -> callSymbol("not", [exp]),
list: list,
str: str,
symbol: _symbol,
_if: _if,
int: int,
float: float,
raw: raw,
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
field: field,
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
begin: (exps:Array<ReaderExp>) -> callSymbol("begin", exps),
set: (v:ReaderExp, value:ReaderExp) -> callSymbol("set", [v, value]),
when: whenUnless.bind("when"),
unless: whenUnless.bind("unless"),
let: let,
objectWith: objectWith,
expFromDef: (def:ReaderExpDef) -> def.withPosOf(posRef),
// Only use within assertion macros
throwAssertionError: () -> {
var usage = "throwAssertionError can only be used in a builder of an assertion macro";
var exps = switch (posRef.def) {
case CallExp(_, exps):
exps;
default:
throw KissError.fromExp(_symbol("throwAssertionError"), usage);
}
var messageExp = if (exps.length > 1) {
exps[1];
} else {
str("");
};
throwAssertOrNeverError(messageExp);
},
neverCase: () -> {
switch (posRef.def) {
case CallExp({pos: _, def: Symbol("never")}, neverExps):
posRef.checkNumArgs(1, 1, '(never <pattern>)');
call(neverExps[0], [
throwAssertOrNeverError(str('case should never match pattern ${Reader.toString(neverExps[0].def)}'))
]);
default:
posRef;
}
},
// Compile-time only!
throwKissError: (reason:String) -> {
callSymbol("throw", [
callSymbol("KissError.fromExpStr", [
// pos
objectWith([
_symbol("file"), str(posRef.pos.file),
_symbol("line"), int(posRef.pos.line),
_symbol("column"), int(posRef.pos.column),
_symbol("absoluteChar"), int(posRef.pos.absoluteChar),
], []),
// expStr
str(Reader.toString(posRef.def)),
str(reason)
])
]);
},
#if macro
haxeExpr: (e:haxe.macro.Expr) -> Helpers.withMacroPosOf(e.expr, posRef),
#end
none: () -> None.withPosOf(posRef)
var messageExp = if (exps.length > 1) {
exps[1];
} else {
str("");
};
return throwAssertOrNeverError(messageExp);
}
public function neverCase() {
return switch (posRef.def) {
case CallExp({pos: _, def: Symbol("never")}, neverExps):
posRef.checkNumArgs(1, 1, '(never <pattern>)');
call(neverExps[0], [
throwAssertOrNeverError(str('case should never match pattern ${Reader.toString(neverExps[0].def)}'))
]);
default:
posRef;
}
}
#end
// Compile-time only!
public function throwKissError(reason:String) {
return callSymbol("throw", [
callSymbol("KissError.fromExpStr", [
// pos
objectWith([
symbol("file"), str(posRef.pos.file),
symbol("line"), int(posRef.pos.line),
symbol("column"), int(posRef.pos.column),
symbol("absoluteChar"), int(posRef.pos.absoluteChar),
], []),
// expStr
str(Reader.toString(posRef.def)),
str(reason)
])
]);
}
#if macro
public function haxeExpr(e:haxe.macro.Expr) {
return Helpers.withMacroPosOf(e.expr, posRef);
}
#end
public function none() {
return None.withPosOf(posRef);
}
public static function checkNumArgs(wholeExp:ReaderExp, min:Null<Int>, max:Null<Int>, ?expectedForm:String) {

View File

@@ -141,13 +141,27 @@ class FieldForms {
throw KissError.fromExp(wholeExp, 'Function or method $field does not exist to be redefined');
}
switch (args[1].def) {
var access = originalFunction.access.copy();
var newFieldNameExp = switch(args[1].def) {
case MetaExp("public", innerExp):
access.remove(APrivate);
access.push(APublic);
innerExp.def;
case MetaExp("private", innerExp):
access.remove(APublic);
access.push(APrivate);
innerExp.def;
case other:
other;
}
switch (newFieldNameExp) {
case Symbol(newFieldName):
var newField = {
pos: wholeExp.macroPos(),
name: newFieldName,
meta: originalFunction.meta,
access: originalFunction.access,
access: access,
kind: FFun(switch(originalFunction.kind) {
case FFun({ret: ret, params: params, args: originalArgs}):
var argIndexMap = new Map<String,Int>();

View File

@@ -268,6 +268,17 @@ class Helpers {
k.addVarInScope(v, true);
}
// Functions declared :Null always return null as Dynamic, to help with annoying type unification situations
// when :Void can't be used
var retString = if (name != null) Helpers.explicitTypeString(name, k) else null;
var ret = if (name != null) Helpers.explicitType(name, k) else null;
if(retString == "Null"){
returnsValue = false;
ret = Helpers.parseComplexType("Dynamic");
var builder = (if (name != null) name else argList).expBuilder();
body.push(builder.callSymbol("return", [builder.symbol("null")]));
}
var expr = if (body.length == 0) {
EReturn(null).withMacroPosOf(if (name != null) name else argList);
} else {
@@ -290,7 +301,7 @@ class Helpers {
// But setting null arguments to default values is so common, and arguments are not settable references,
// so function args are not immutable.
return {
ret: if (name != null) Helpers.explicitType(name, k) else null,
ret: ret,
args: args,
expr: expr,
params: params
@@ -461,6 +472,10 @@ class Helpers {
UnquoteList(removeTypeAnnotations(innerExp));
case None:
None;
case ListEatingExp(exps):
ListEatingExp(exps.map(removeTypeAnnotations));
case ListRestExp(name):
ListRestExp(name);
default:
throw KissError.fromExp(exp, 'cannot remove type annotations');
};
@@ -511,6 +526,7 @@ class Helpers {
// The macro interpreter gets everything a KissInterp has,
// plus macro-specific things.
var interp = new KissInterp();
interp.variables.set("kissFile", k.file);
interp.variables.set("read", Reader._assertRead.bind(_, k));
interp.variables.set("readOr", Reader._readOr.bind(_, k));
interp.variables.set("readExpArray", Reader._readExpArray.bind(_, _, k));
@@ -749,6 +765,12 @@ class Helpers {
if (FileSystem.exists(Path.join([githubPath, "haxelib.json"]))) return githubPath;
}
// <libname>/<version>/git/<commit>/<classPath...>
if (parts[matchingPartIndex + 2] == "git") {
var gitPath = parts.slice(0, matchingPartIndex + 4).join("/");
if (FileSystem.exists(Path.join([gitPath, "haxelib.json"]))) return gitPath;
}
matchingPartIndex = parts.indexOf(haxelibName, matchingPartIndex + 1);
}
}

View File

@@ -165,6 +165,7 @@ class Kiss {
],
identAliases: [
// These ones won't conflict with variables and might commonly be used with (apply)
"extractOpt" => Symbol("Prelude.extractOpt"),
"+" => Symbol("Prelude.add"),
"-" => Symbol("Prelude.subtract"),
"*" => Symbol("Prelude.multiply"),
@@ -613,9 +614,11 @@ class Kiss {
var rebuildMTime = Math.NEGATIVE_INFINITY;
for (path in pathsWhichTriggerRebuild) {
var fileMTime = sys.FileSystem.stat(path).mtime.getTime();
if (fileMTime > rebuildMTime) {
rebuildMTime = fileMTime;
if(sys.FileSystem.exists(path)){
var fileMTime = sys.FileSystem.stat(path).mtime.getTime();
if (fileMTime > rebuildMTime) {
rebuildMTime = fileMTime;
}
}
}

34
src/kiss/KissInterp2.hx Normal file
View File

@@ -0,0 +1,34 @@
package kiss;
#if macro
import kiss.Kiss;
import kiss.Prelude;
import haxe.macro.Expr;
import haxe.macro.Context;
class KissInterp2 {
public static function build():Array<Field> {
var fields = Kiss.build(Prelude.joinPath(Helpers.libPath("kiss"), "src/kiss/KissInterp2.kiss"));
// TODO put imported types into the global variables interp
var imports = Context.getLocalImports();
fields.push({
pos: Context.currentPos(),
name: "new",
access: [
APublic
],
kind: FFun({
args: [],
expr: macro {
specialForms = _specialForms();
}
})
});
return fields;
}
}
#end

83
src/kiss/KissInterp2.kiss Normal file
View File

@@ -0,0 +1,83 @@
(importWithDefAlias)
(import kiss.Reader)
(import kiss.Reader.ReadFunction)
(import kiss.Reader.ReadTable)
(import kiss.ReaderExp)
(import kiss.ReaderExp.ReaderExpDef)
(import kiss.ReaderExp.ReaderExpDef.Symbol)
(import kiss.ReaderExp.ReaderExpDef.FieldExp)
(import kiss.Stream)
(prop &mut :ReadTable readTable (Reader.builtins))
(prop &mut :ReadTable startOfLineReadTable (new Map))
(prop &mut :ReadTable startOfFileReadTable (new Map))
(prop &mut :ReadTable endOfFileReadTable (new Map))
(prop &mut :Map<String,ReaderExpDef> identAliases (new Map))
(prop :Map<String,Dynamic> globals [=>"false" false =>"true" true =>"null" null])
(prop :Array<Map<String,Dynamic>> localScopes [])
(prop :Map<String,(Array<ReaderExp>,Dynamic->Void)->Void> specialForms)
(method :Map<String,(Array<ReaderExp>,Dynamic->Void)->Void> _specialForms [] [
=>"if"
->[args cc]
(evalCC (first ~args)
->val
(if val
(evalCC (second args) cc)
(evalCC (third args) cc)))
])
(method :Void evalCC [:Dynamic input :Dynamic->Void cc]
// Std.isOfType can't handle typedefs
(when (and (Reflect.hasField input "pos") (Reflect.hasField input "def"))
(evalCC input.def cc)
(return))
(typeCase [input]
([:String str]
(let [stream (Stream.fromString str)]
(evalCC stream cc)))
([:Stream s]
(ifLet [(Some exp) (Reader.read s this)]
(evalCC exp.def cc)
(throw "Couldn't read valid expression from $s")))
([:ReaderExpDef def]
(case def
// Special form call
((when (specialForms.exists form) (CallExp (object def (Symbol form)) args))
((dictGet specialForms form) args cc))
// Field access
((FieldExp field obj safe)
(evalCC obj ->v
(if ~v
(cc ~(Reflect.getProperty v field))
(if safe
(cc null)
(throw "field access on null! $(Reader.toString obj.def)")))))
// Symbol
((Symbol ident)
// Check for numbers
(let [f (Std.parseFloat ident)]
(unless (Math.isNaN f)
(cc f)
(return)))
// Check for field access
(let [idx (ident.indexOf ".")]
(unless (= -1 idx)
(let [parts (ident.split ".")
&mut exp (object pos null def (Symbol (first parts)))]
(doFor part (parts.slice 1)
(let [safe (StringTools.startsWith part "?")]
(when safe (set part (part.substr 1)))
(set exp (object pos null def (FieldExp part exp safe)))))
(evalCC exp cc)
(return))))
(doFor i (range localScopes.length)
(let [scope (nth localScopes (- localScopes.length i 1))]
(when (scope.exists ident)
(cc (dictGet scope ident))
(return))))
(cc (dictGet globals ident)))
(never otherwise)))
(otherwise (throw "Can't interpret ${input}"))))

View File

@@ -532,7 +532,7 @@ class Macros {
args[innerArgNames.shift()] = innerExps[idx];
}
for (idx in optIndex...restIndex) {
args[innerArgNames.shift()] = if (exps.length > idx) innerExps[idx] else null;
args[innerArgNames.shift()] = if (innerExps.length > idx) innerExps[idx] else null;
}
if (innerArgNames.length > 0) {
var restArgs = innerExps.slice(restIndex);

View File

@@ -6,6 +6,7 @@ import haxe.macro.Expr;
import haxe.macro.Context;
import haxe.macro.Type;
import kiss.Kiss;
import kiss.Helpers;
import kiss.Reader;
import kiss.Stream;
@@ -20,12 +21,33 @@ import sys.io.Process;
import sys.FileSystem;
using StringTools;
using haxe.io.Path;
class Main {
static function main() {
macroMain();
}
static function libPath(lib:String) {
#if macro
try {
return Helpers.libPath(lib);
} catch (e) {
// The library isn't in the classpaths but it might be in the same folder
// as kiss.
var kissPath = Helpers.libPath("kiss");
var failureMessage = "Can't find libPath for " + lib + " relative to " + kissPath;
if (FileSystem.isDirectory('${kissPath.directory()}/${lib}')) {
return '${kissPath.directory()}/${lib}';
} else {
throw failureMessage;
}
}
#end
throw 'Tried to get libPath outside of macroMain()';
return "";
}
// When called from the command-line, Kiss has various subcommands, some of which can only run in macro context
static macro function macroMain():Expr {
var args = Sys.args();
@@ -92,7 +114,7 @@ class Main {
return input;
}
static function _makeFileForNewProject(templateDir:String, templateFile:Array<String>, workingDir:String, projectName:String, pkg:String) {
static function _makeFileForNewProject(templateDir:String, templateFile:Array<String>, workingDir:String, projectName:String, description:String, pkg:String) {
// Expand this list when making new templates with different binary extensions
var extensionsForBytes = [
"png"
@@ -108,14 +130,28 @@ class Main {
var fullTemplateFilePath = Path.join([templateDir, "template"].concat(templateFile));
var newFileContent:Dynamic = getContent(fullTemplateFilePath);
if (replaceStringTemplate)
newFileContent = StringTools.replace(newFileContent, "template", pkg);
if (replaceStringTemplate) {
var projectOrPackageName = if (['hx', 'hxml', 'kiss'].contains(fullTemplateFilePath.extension())) {
pkg;
} else {
projectName;
}
newFileContent = StringTools.replace(newFileContent, "template", projectOrPackageName);
newFileContent = StringTools.replace(newFileContent, "{{description}}", pkg);
}
var templateFileInNewProject = [for (part in templateFile) if (part == "template") pkg else part];
var lastPart = templateFileInNewProject.pop();
var base = lastPart.withoutExtension();
var ext = lastPart.extension();
if(base == "template"){
lastPart = pkg.withExtension(ext);
}
templateFileInNewProject.push(lastPart);
var newFilePath = Path.join([workingDir, projectName].concat(templateFileInNewProject));
saveContent(newFilePath, newFileContent);
}
static function _makeFolderForNewProject(templateDir:String, templateFolder:Array<String>, workingDir:String, projectName:String, pkg:String) {
static function _makeFolderForNewProject(templateDir:String, templateFolder:Array<String>, workingDir:String, projectName:String, description:String, pkg:String) {
var fullTemplateFolderPath = Path.join([templateDir, "template"].concat(templateFolder));
var templateFolderInNewProject = [for (part in templateFolder) if (part == "template") pkg else part];
var newFolderPath = Path.join([workingDir, projectName].concat(templateFolderInNewProject));
@@ -123,30 +159,32 @@ class Main {
for (fileOrFolder in FileSystem.readDirectory(fullTemplateFolderPath)) {
if (FileSystem.isDirectory(Path.join([fullTemplateFolderPath, fileOrFolder]))) {
_makeFolderForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, pkg);
_makeFolderForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, description, pkg);
} else {
_makeFileForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, pkg);
_makeFileForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, description, pkg);
}
}
}
static function newProject(args:Array<String>) {
var kissLibPath = new Process("haxelib", ["libpath", "kiss"]).stdout.readAll().toString().trim();
var kissLibPath = libPath("kiss");
var name = promptFor("name");
// TODO put the prompted name and description in a README.md
var pkg = name.toLowerCase().replace("-", "_");
var description = "";
var haxelibJson = {
"name": name,
"contributors": promptFor("authors (comma-separated)").split(",").map(StringTools.trim),
// TODO can make the default URL actually point to the projects subdirectory... but only want that functionality if the working dir is in kisslang/projects
"url": promptFor("url", "https://github.com/NQNStudios/kisslang"),
"url": promptFor("url", 'https://github.com/kiss-lang/${name}'),
"license": promptFor("license", "LGPL"),
"tags": {
var t = promptFor("tags (comma-separated)", "").split(",").map(StringTools.trim);
t.remove("");
t;
},
"description": promptFor("description", ""),
"description": {
description = promptFor("description", "");
description;
},
"version": "0.0.0",
"releasenote": "",
"classPath": "src/",
@@ -155,11 +193,13 @@ class Main {
"kiss": ""
}
};
var workingDir = Sys.args().pop();
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissLibPath, _, workingDir, name, pkg);
FileSystem.createDirectory(Path.join([workingDir, name, "src", pkg]));
makeFileForNewProject(["src", "template", "Main.hx"]);
makeFileForNewProject(["src", "template", "Main_.kiss"]);
var workingDir = Sys.getCwd();
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissLibPath, _, workingDir, name, description, pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissLibPath, _, workingDir, name, description, pkg);
makeFolderForNewProject(["haxe_libraries"]);
makeFolderForNewProject(["src"]);
makeFileForNewProject([".haxerc"]);
makeFileForNewProject(["build.hxml"]);
makeFileForNewProject(["build.hxml"]);
makeFileForNewProject(["test.sh"]);
File.saveContent(Path.join([workingDir, name, 'haxelib.json']), Json.stringify(haxelibJson, null, "\t"));
@@ -173,7 +213,7 @@ class Main {
var background = promptFor("background color", "#000000");
var kissFlixelLibPath = new Process("haxelib", ["libpath", "kiss-flixel"]).stdout.readAll().toString().trim();
var workingDir = Sys.args().pop();
var workingDir = Sys.getCwd();
FileSystem.createDirectory(Path.join([workingDir, title]));
// Substitute the specified values into the Project.xml:
@@ -191,8 +231,8 @@ class Main {
firstWindowElement.set("background", background);
File.saveContent(Path.join([workingDir, title, 'Project.xml']), projectXml.toString());
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissFlixelLibPath, _, workingDir, title, "");
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissFlixelLibPath, _, workingDir, title, "");
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissFlixelLibPath, _, workingDir, title, "", "");
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissFlixelLibPath, _, workingDir, title, "", "");
makeFolderForNewProject([".vscode"]);
makeFolderForNewProject(["assets"]);
makeFolderForNewProject(["source"]);
@@ -201,17 +241,22 @@ class Main {
}
static function newExpressProject(args:Array<String>) {
var kissExpressLibPath = libPath("kiss-express");
var title = promptFor("title (lower-case!)").toLowerCase();
var pkg = title.replace("-", "_");
var kissExpressLibPath = new Process("haxelib", ["libpath", "kiss-express"]).stdout.readAll().toString().trim();
var workingDir = Sys.args().pop();
var workingDir = Sys.getCwd();
var projectDir = Path.join([workingDir, title]);
FileSystem.createDirectory(projectDir);
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissExpressLibPath, _, workingDir, title, pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissExpressLibPath, _, workingDir, title, pkg);
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissExpressLibPath, _, workingDir, title, "", pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissExpressLibPath, _, workingDir, title, "", pkg);
makeFolderForNewProject(["externs"]);
makeFolderForNewProject(["src", "template"]);
makeFileForNewProject([".gitignore"]);
makeFileForNewProject(["template.service"]);
makeFileForNewProject([".haxerc"]);
Sys.setCwd(projectDir);
Sys.println(new Process("lix", ["install", "gh:kiss-lang/kiss-express"]).stdout.readAll().toString().trim());
makeFileForNewProject(["build.hxml"]);
{
makeFileForNewProject(["package.json"]);
@@ -225,31 +270,27 @@ class Main {
static function newVscodeProject(args:Array<String>) {
var title = promptFor("title (lower-case!)").toLowerCase();
var description = promptFor("description");
var pkg = title.replace("-", "_");
var kissVscodeApiLibPath = new Process("haxelib", ["libpath", "kiss-vscode-api"]).stdout.readAll().toString().trim();
var workingDir = Sys.args().pop();
var workingDir = Sys.getCwd();
var projectDir = Path.join([workingDir, title]);
FileSystem.createDirectory(projectDir);
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, pkg);
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, description, pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, description, pkg);
makeFolderForNewProject(["src"]);
makeFolderForNewProject([".vscode"]);
makeFileForNewProject([".gitignore"]);
makeFileForNewProject([".vscodeignore"]);
makeFileForNewProject(["README.md"]);
makeFileForNewProject(["build.hxml"]);
{
makeFileForNewProject(["package.json"]);
var packageFile = Path.join([projectDir, "package.json"]);
var packageJson = Json.parse(File.getContent(packageFile));
packageJson.name = title;
File.saveContent(packageFile, Json.stringify(packageJson, null, "\t"));
}
makeFileForNewProject(["package.json"]);
makeFileForNewProject(["test.sh"]);
}
static function newFirefoxProject(args:Array<String>) {
var kissFirefoxLibPath = libPath("kiss-firefox");
var title = promptFor("title (lower-case!)").toLowerCase();
var description = promptFor("description");
var pkg = title.replace("-", "_");
@@ -260,16 +301,18 @@ class Main {
break;
urlPatterns.push(nextPattern);
}
var kissFirefoxLibPath = new Process("haxelib", ["libpath", "kiss-firefox"]).stdout.readAll().toString().trim();
var workingDir = Sys.args().pop();
var workingDir = Sys.getCwd();
var projectDir = Path.join([workingDir, title]);
FileSystem.createDirectory(projectDir);
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, pkg);
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, description, pkg);
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, description, pkg);
makeFolderForNewProject(["src"]);
makeFolderForNewProject(["icons"]);
makeFileForNewProject([".gitignore"]);
makeFileForNewProject([".haxerc"]);
Sys.setCwd(projectDir);
Sys.println(new Process("lix", ["install", "gh:kiss-lang/kiss-firefox"]).stdout.readAll().toString().trim());
makeFileForNewProject(["build.hxml"]);
{
makeFileForNewProject(["manifest.json"]);

View File

@@ -4,6 +4,7 @@ using Std;
import kiss.ReaderExp;
import haxe.ds.Either;
import haxe.ds.Option;
import haxe.Constraints;
import haxe.DynamicAccess;
#if js
@@ -76,6 +77,15 @@ class Prelude {
};
}
public static function extractOpt<T>(opt:Option<T>, ?def:T) {
return switch (opt) {
case Some(v): v;
default:
if(def != null) def;
else throw 'Failed to extract Option: $opt';
};
}
static function _and(values:Array<Dynamic>):Dynamic {
for (value in values) {
if (!truthy(value)) {
@@ -604,6 +614,24 @@ class Prelude {
};
}
public static function callable(callExp:ReaderExp) {
return switch (callExp.def) {
case CallExp(_callable, _):
_callable;
default:
throw KissError.fromExp(callExp, 'Expected a CallExp');
}
}
public static function callArgs(callExp:ReaderExp) {
return switch (callExp.def) {
case CallExp(_, _args):
_args;
default:
throw KissError.fromExp(callExp, 'Expected a CallExp');
}
}
public static function uuid() {
return Uuid.v4().toShort();
}
@@ -918,7 +946,7 @@ class Prelude {
static var shellCount = 0;
public static function shellExecute(script:String, shell:String) {
public static function shellExecute(script:String, shell:String):String {
#if ((sys || hxnodejs) && !frontend)
if (shell.length == 0) {
shell = if (Sys.systemName() == "Windows") "cmd /c" else "bash";
@@ -937,13 +965,14 @@ class Prelude {
if (Sys.systemName() != "Windows") tempScript = joinPath(Sys.getCwd(), tempScript);
var parts = shell.split(" ").concat([tempScript]);
var shell = parts.shift();
assertProcess(shell, parts);
return assertProcess(shell, parts);
FileSystem.deleteFile(tempScript);
} catch (e) {
printStr('# Failing script:');
printStr(script);
printStr('#################');
FileSystem.deleteFile(tempScript);
print(e);
throw e;
}
@@ -969,7 +998,9 @@ class Prelude {
#if js
public static dynamic function makeAwaitLetDefaultCatch<TOut>(binding:String):PromiseHandler<Dynamic,TOut> {
return function (reason:Dynamic):Promise<TOut> {
throw 'awaitLet $binding rejected promise: $reason';
var message = 'awaitLet $binding rejected promise: $reason';
print(message);
throw message;
};
}

View File

@@ -178,7 +178,7 @@ class Reader {
// -+>countVar arg body
// -+>countVar {body}
// -+>countVar (body)
// or any of those with the first expression after -> or -+> prefixed by :Void
// or any of those with the first expression after -> or -+> prefixed by :Void or :Null
function arrowSyntax(countingLambda:Bool, stream:Stream, k:HasReadTables) {
var countVar = if (countingLambda) {
_assertRead(stream, k);
@@ -192,10 +192,14 @@ class Reader {
var bodyExp:ReaderExp = null;
var returnsValue = true;
var returnsNull = false;
switch (firstExp.def) {
case TypedExp("Void", realFirstExp):
firstExp = realFirstExp;
returnsValue = false;
case TypedExp("Null", realFirstExp):
firstExp = realFirstExp;
returnsNull = true;
default:
}
switch (firstExp.def) {
@@ -209,10 +213,13 @@ class Reader {
argsExp = b.list([]);
bodyExp = firstExp;
default:
throw KissError.fromExp(firstExp, "first expression after -> should be [args...], arg, (exp) or {body}, or one of those prefixed with :Void. When an argument type must be specified, even a single argument name must be put in brackets. For example: ->[:ArgType arg] <exp>");
throw KissError.fromExp(firstExp, "first expression after -> should be [args...], arg, (exp) or {body}, or one of those prefixed with :Void or :Null. When an argument type must be specified, even a single argument name must be put in brackets. For example: ->[:ArgType arg] <exp>");
}
if (!returnsValue) {
argsExp = TypedExp("Void", argsExp).withPosOf(argsExp);
} else if(returnsNull) {
argsExp = TypedExp("Null", argsExp).withPosOf(argsExp);
bodyExp = b.begin([bodyExp, b.callSymbol("return", [b.symbol("null")])]);
}
return if (countingLambda) {
CallExp(b.symbol("countingLambda"), [countVar, argsExp, bodyExp]);

View File

@@ -42,6 +42,7 @@ class SpecialForms {
k.formDocs[newName] = k.formDocs[oldName];
}
var unops = ["++", "--"];
map["begin"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
// Sometimes empty blocks are useful, so a checkNumArgs() seems unnecessary here for now.
@@ -53,7 +54,7 @@ class SpecialForms {
}
for (bodyExp in args) {
switch(bodyExp.def) {
case Symbol(_) if (lastArg != null):
case Symbol(name) if (lastArg != null && !unops.contains(name.substr(0, 2)) && !unops.contains(name.substr(name.length - 2, 2))):
KissError.warnFromExp(bodyExp, "This looks like an unused value");
default:
}
@@ -232,7 +233,7 @@ class SpecialForms {
};
}
k.doc("deflocal", 2, 3, "(localVar <optional :type> <variable> <optional: &mut> <value>)");
k.doc("deflocal", 2, 3, "(localVar <optional: &mut> <optional :type> <variable> <value>)");
map["deflocal"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
k.localVarCalls.push(wholeExp);
k.localVarWarning();
@@ -270,12 +271,15 @@ class SpecialForms {
block;
};
k.doc("lambda", 2, null, "(lambda [<argsNames...>] <body...>)");
k.doc("lambda", 2, null, "(lambda <optional :Void or :Null> [<argsNames...>] <body...>)");
map["lambda"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
var returnsValue = switch (args[0].def) {
case TypedExp("Void", argNames):
args[0] = argNames;
false;
case TypedExp("Null", argNames):
args[0] = argNames;
true;
default:
true;
}
@@ -468,12 +472,11 @@ class SpecialForms {
};
// Type check syntax:
k.doc("the", 2, 3, '(the <type> <value>)');
k.doc("the", 2, 3, '(the <?package> <type> <value>)');
map["the"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
var pkg = "";
var whichArg = "first";
if (args.length == 3) {
throw KissError.fromExp(wholeExp, "(the <package> <Type> <value>) form is no longer allowed. use (the <package.Type> <value>) instead");
pkg = switch (args.shift().def) {
case Symbol(pkg): pkg;
default: throw KissError.fromExp(wholeExp, '$whichArg argument to (the... ) should be a valid haxe package');

View File

@@ -90,6 +90,14 @@ class Stream {
return Some(content.substr(0, chars));
}
// Peek until the end of the line or EOF
public function peekLine():Option<String> {
if(content.length == 0) return None;
var index = content.indexOf("\n");
if(index == -1) return Some(content);
return Some(content.substr(0, index));
}
public function isEmpty() {
return content.length == 0;
}
@@ -418,6 +426,34 @@ class Stream {
};
}
// As long as lines keep passing a predicate, keep adding them to a Stream, and return it
public function takeLinesAsStreamWhile(predicate:String->Bool):Option<Stream> {
var lineNo = this.line;
var column = this.column;
var absoluteChar = this.absoluteChar;
var newContent = "";
while (true){
switch (peekLine()){
case Some(line) if(predicate(line)):
newContent += line + "\n";
takeLine();
default:
break;
}
}
if(newContent.length == 0) return None;
// Remove trailing newline
newContent = newContent.substr(0, newContent.length - 1);
var s = Stream.fromString(newContent);
s.line = lineNo;
s.column = column;
s.file = this.file;
s.absoluteChar = absoluteChar;
return Some(s);
}
public function expect(whatToExpect:String="something unspecified", f:Void->Option<String>):String {
var position = position();
switch (f()) {

View File

@@ -0,0 +1,25 @@
package test.cases;
import utest.Test;
import utest.Assert;
import kiss.Prelude;
#if js
import js.lib.Promise;
#end
import utest.Async;
@:build(kiss.KissInterp2.build())
class Interp {}
@:build(kiss.Kiss.build())
class KissInterp2TestCase extends Test {
function testEvalGlobal() {
_testEvalGlobal();
}
function testIf() {
_testIf();
}
function testField() {
_testField();
}
}

View File

@@ -0,0 +1,18 @@
(defMacro assertEval [expected exp]
`(interp.evalCC ,exp ->v (Assert.equals ,expected v)))
(function _testEvalGlobal []
(let [interp (new Interp)]
(dictSet interp.globals "a" 5)
(assertEval 5 "a")))
(function _testIf []
(let [interp (new Interp)]
(assertEval 5 "(if true 5 3)")
(assertEval 3 "(if false 5 3)")))
(function _testField []
(let [interp (new Interp)]
(dictSet interp.globals "obj" (object a 5 b (object c 3)))
(assertEval 5 "obj.a")
(assertEval 3 "obj.b.c")))

4
template/.haxerc Normal file
View File

@@ -0,0 +1,4 @@
{
"version": "4.3.1",
"resolveLibs": "scoped"
}

2
template/README.md Normal file
View File

@@ -0,0 +1,2 @@
# template
{{description}}

View File

@@ -0,0 +1,5 @@
# @install: lix --silent download "haxelib:/haxe-strings#7.0.3" into haxe-strings/7.0.3/haxelib
-cp ${HAXE_LIBCACHE}/haxe-strings/7.0.3/haxelib/src/
-D haxe-strings=7.0.3
--macro hx.strings.internal.Macros.addDefines()
--macro hx.strings.internal.Macros.configureNullSafety()

View File

@@ -0,0 +1,5 @@
# @install: lix --silent download "haxelib:/hscript#2.5.0" into hscript/2.5.0/haxelib
# @run: haxelib run-dir hscript "${HAXE_LIBCACHE}/hscript/2.5.0/haxelib"
-cp ${HAXE_LIBCACHE}/hscript/2.5.0/haxelib/
-D hscript=2.5.0
--macro keep('IntIterator')

View File

@@ -0,0 +1,12 @@
# @install: lix --silent download "gh://github.com/kiss-lang/kiss#877b965812be5013c514d03d6f94a074495a53fa" into kiss/0.0.1/github/877b965812be5013c514d03d6f94a074495a53fa
# @run: haxelib run-dir kiss "${HAXE_LIBCACHE}/kiss/0.0.1/github/877b965812be5013c514d03d6f94a074495a53fa"
-lib haxe-strings
-lib hscript
-lib tink_json
-lib tink_macro
-lib tink_syntaxhub
-lib uuid
-cp ${HAXE_LIBCACHE}/kiss/0.0.1/github/877b965812be5013c514d03d6f94a074495a53fa/src
-D kiss=0.0.1
-w -WUnusedPattern
--macro kiss.KissFrontend.use()

View File

@@ -0,0 +1,3 @@
# @install: lix --silent download "haxelib:/tink_core#2.1.0" into tink_core/2.1.0/haxelib
-cp ${HAXE_LIBCACHE}/tink_core/2.1.0/haxelib/src
-D tink_core=2.1.0

View File

@@ -0,0 +1,4 @@
# @install: lix --silent download "haxelib:/tink_json#0.11.0" into tink_json/0.11.0/haxelib
-lib tink_typecrawler
-cp ${HAXE_LIBCACHE}/tink_json/0.11.0/haxelib/src
-D tink_json=0.11.0

View File

@@ -0,0 +1,4 @@
# @install: lix --silent download "gh://github.com/kiss-lang/tink_macro#8b60a484b1141d1176b34ba3af9ac65b499079ff" into tink_macro/1.0.3/github/8b60a484b1141d1176b34ba3af9ac65b499079ff
-lib tink_core
-cp ${HAXE_LIBCACHE}/tink_macro/1.0.3/github/8b60a484b1141d1176b34ba3af9ac65b499079ff/src
-D tink_macro=1.0.3

View File

@@ -0,0 +1,3 @@
-D tink_priority=0.1.3
# @install: lix --silent download "gh://github.com/haxetink/tink_priority#ea736d31dc788aae703a2aa415c25d5b80d0e7d1" into tink_priority/0.1.3/github/ea736d31dc788aae703a2aa415c25d5b80d0e7d1
-cp ${HAXE_LIBCACHE}/tink_priority/0.1.3/github/ea736d31dc788aae703a2aa415c25d5b80d0e7d1/src

View File

@@ -0,0 +1,6 @@
# @install: lix --silent download "gh://github.com/haxetink/tink_syntaxhub#b6ea4966bbdee4d176ac8dd5d2d8ae3b362b2f86" into tink_syntaxhub/0.6.0/github/b6ea4966bbdee4d176ac8dd5d2d8ae3b362b2f86
-lib tink_macro
-lib tink_priority
-cp ${HAXE_LIBCACHE}/tink_syntaxhub/0.6.0/github/b6ea4966bbdee4d176ac8dd5d2d8ae3b362b2f86/src
-D tink_syntaxhub=0.6.0
--macro tink.SyntaxHub.use()

View File

@@ -0,0 +1,4 @@
# @install: lix --silent download "haxelib:/tink_typecrawler#0.7.0" into tink_typecrawler/0.7.0/haxelib
-lib tink_macro
-cp ${HAXE_LIBCACHE}/tink_typecrawler/0.7.0/haxelib/src
-D tink_typecrawler=0.7.0

View File

@@ -0,0 +1,3 @@
# @install: lix --silent download "haxelib:/uuid#2.4.1" into uuid/2.4.1/haxelib
-cp ${HAXE_LIBCACHE}/uuid/2.4.1/haxelib/src
-D uuid=2.4.1