Compare commits
1 Commits
8792a36dfe
...
fix-things
Author | SHA1 | Date | |
---|---|---|---|
2ea0066d32 |
23
.github/workflows/test.yml
vendored
23
.github/workflows/test.yml
vendored
@@ -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,12 +33,13 @@ jobs:
|
||||
# Set up Kiss runtimes:
|
||||
|
||||
# nodejs
|
||||
# - uses: actions/setup-node@v3
|
||||
# with:
|
||||
# node-version: ${{ matrix.node-version }}
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
if: matrix.test-target == 'nodejs'
|
||||
|
||||
# lix
|
||||
- uses: https://k7izh9.gitea.cloud/kiss-lang/setup-lix@1.0.2
|
||||
- uses: lix-pm/setup-lix@master
|
||||
with:
|
||||
lix-version: 15.12.0
|
||||
|
||||
@@ -49,8 +50,6 @@ 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')
|
||||
|
||||
|
@@ -4,4 +4,5 @@
|
||||
-lib tink_macro
|
||||
-lib tink_syntaxhub
|
||||
-lib haxe-strings
|
||||
-cp src
|
||||
--run kiss.Main
|
@@ -1,7 +0,0 @@
|
||||
-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")
|
@@ -1,4 +1,4 @@
|
||||
# @install: lix --silent download "git:https://k7izh9.gitea.cloud/kiss-lang/tink_macro#8b60a484b1141d1176b34ba3af9ac65b499079ff" into tink_macro/1.0.3/git/8b60a484b1141d1176b34ba3af9ac65b499079ff
|
||||
# @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/git/8b60a484b1141d1176b34ba3af9ac65b499079ff/src
|
||||
-cp ${HAXE_LIBCACHE}/tink_macro/1.0.3/github/8b60a484b1141d1176b34ba3af9ac65b499079ff/src
|
||||
-D tink_macro=1.0.3
|
@@ -5,164 +5,133 @@ 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 {
|
||||
var posRef:ReaderExp;
|
||||
|
||||
function new(posRef:ReaderExp) {
|
||||
this.posRef = posRef;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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 _symbol(?name:String) {
|
||||
return Prelude.symbol(name).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)}'))
|
||||
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)
|
||||
])
|
||||
]);
|
||||
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);
|
||||
},
|
||||
#if macro
|
||||
haxeExpr: (e:haxe.macro.Expr) -> Helpers.withMacroPosOf(e.expr, posRef),
|
||||
#end
|
||||
none: () -> None.withPosOf(posRef)
|
||||
};
|
||||
}
|
||||
|
||||
public static function checkNumArgs(wholeExp:ReaderExp, min:Null<Int>, max:Null<Int>, ?expectedForm:String) {
|
||||
|
@@ -141,27 +141,13 @@ class FieldForms {
|
||||
throw KissError.fromExp(wholeExp, 'Function or method $field does not exist to be redefined');
|
||||
}
|
||||
|
||||
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) {
|
||||
switch (args[1].def) {
|
||||
case Symbol(newFieldName):
|
||||
var newField = {
|
||||
pos: wholeExp.macroPos(),
|
||||
name: newFieldName,
|
||||
meta: originalFunction.meta,
|
||||
access: access,
|
||||
access: originalFunction.access,
|
||||
kind: FFun(switch(originalFunction.kind) {
|
||||
case FFun({ret: ret, params: params, args: originalArgs}):
|
||||
var argIndexMap = new Map<String,Int>();
|
||||
|
@@ -268,17 +268,6 @@ 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 {
|
||||
@@ -301,7 +290,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: ret,
|
||||
ret: if (name != null) Helpers.explicitType(name, k) else null,
|
||||
args: args,
|
||||
expr: expr,
|
||||
params: params
|
||||
@@ -472,10 +461,6 @@ 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');
|
||||
};
|
||||
@@ -526,7 +511,6 @@ 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));
|
||||
@@ -765,12 +749,6 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@@ -165,7 +165,6 @@ 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"),
|
||||
@@ -614,11 +613,9 @@ class Kiss {
|
||||
|
||||
var rebuildMTime = Math.NEGATIVE_INFINITY;
|
||||
for (path in pathsWhichTriggerRebuild) {
|
||||
if(sys.FileSystem.exists(path)){
|
||||
var fileMTime = sys.FileSystem.stat(path).mtime.getTime();
|
||||
if (fileMTime > rebuildMTime) {
|
||||
rebuildMTime = fileMTime;
|
||||
}
|
||||
var fileMTime = sys.FileSystem.stat(path).mtime.getTime();
|
||||
if (fileMTime > rebuildMTime) {
|
||||
rebuildMTime = fileMTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,34 +0,0 @@
|
||||
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
|
@@ -1,83 +0,0 @@
|
||||
(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}"))))
|
@@ -532,7 +532,7 @@ class Macros {
|
||||
args[innerArgNames.shift()] = innerExps[idx];
|
||||
}
|
||||
for (idx in optIndex...restIndex) {
|
||||
args[innerArgNames.shift()] = if (innerExps.length > idx) innerExps[idx] else null;
|
||||
args[innerArgNames.shift()] = if (exps.length > idx) innerExps[idx] else null;
|
||||
}
|
||||
if (innerArgNames.length > 0) {
|
||||
var restArgs = innerExps.slice(restIndex);
|
||||
|
117
src/kiss/Main.hx
117
src/kiss/Main.hx
@@ -6,7 +6,6 @@ import haxe.macro.Expr;
|
||||
import haxe.macro.Context;
|
||||
import haxe.macro.Type;
|
||||
import kiss.Kiss;
|
||||
import kiss.Helpers;
|
||||
import kiss.Reader;
|
||||
import kiss.Stream;
|
||||
|
||||
@@ -21,33 +20,12 @@ 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();
|
||||
@@ -114,7 +92,7 @@ class Main {
|
||||
return input;
|
||||
}
|
||||
|
||||
static function _makeFileForNewProject(templateDir:String, templateFile:Array<String>, workingDir:String, projectName:String, description:String, pkg:String) {
|
||||
static function _makeFileForNewProject(templateDir:String, templateFile:Array<String>, workingDir:String, projectName:String, pkg:String) {
|
||||
// Expand this list when making new templates with different binary extensions
|
||||
var extensionsForBytes = [
|
||||
"png"
|
||||
@@ -130,28 +108,14 @@ class Main {
|
||||
|
||||
var fullTemplateFilePath = Path.join([templateDir, "template"].concat(templateFile));
|
||||
var newFileContent:Dynamic = getContent(fullTemplateFilePath);
|
||||
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);
|
||||
}
|
||||
if (replaceStringTemplate)
|
||||
newFileContent = StringTools.replace(newFileContent, "template", 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, description:String, pkg:String) {
|
||||
static function _makeFolderForNewProject(templateDir:String, templateFolder:Array<String>, workingDir:String, projectName: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));
|
||||
@@ -159,32 +123,30 @@ class Main {
|
||||
|
||||
for (fileOrFolder in FileSystem.readDirectory(fullTemplateFolderPath)) {
|
||||
if (FileSystem.isDirectory(Path.join([fullTemplateFolderPath, fileOrFolder]))) {
|
||||
_makeFolderForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, description, pkg);
|
||||
_makeFolderForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, pkg);
|
||||
} else {
|
||||
_makeFileForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, description, pkg);
|
||||
_makeFileForNewProject(templateDir, templateFolder.concat([fileOrFolder]), workingDir, projectName, pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function newProject(args:Array<String>) {
|
||||
var kissLibPath = libPath("kiss");
|
||||
var kissLibPath = new Process("haxelib", ["libpath", "kiss"]).stdout.readAll().toString().trim();
|
||||
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),
|
||||
"url": promptFor("url", 'https://github.com/kiss-lang/${name}'),
|
||||
// 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"),
|
||||
"license": promptFor("license", "LGPL"),
|
||||
"tags": {
|
||||
var t = promptFor("tags (comma-separated)", "").split(",").map(StringTools.trim);
|
||||
t.remove("");
|
||||
t;
|
||||
},
|
||||
"description": {
|
||||
description = promptFor("description", "");
|
||||
description;
|
||||
},
|
||||
"description": promptFor("description", ""),
|
||||
"version": "0.0.0",
|
||||
"releasenote": "",
|
||||
"classPath": "src/",
|
||||
@@ -193,13 +155,11 @@ class 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"]);
|
||||
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"]);
|
||||
makeFileForNewProject(["build.hxml"]);
|
||||
makeFileForNewProject(["test.sh"]);
|
||||
File.saveContent(Path.join([workingDir, name, 'haxelib.json']), Json.stringify(haxelibJson, null, "\t"));
|
||||
@@ -213,7 +173,7 @@ class Main {
|
||||
var background = promptFor("background color", "#000000");
|
||||
|
||||
var kissFlixelLibPath = new Process("haxelib", ["libpath", "kiss-flixel"]).stdout.readAll().toString().trim();
|
||||
var workingDir = Sys.getCwd();
|
||||
var workingDir = Sys.args().pop();
|
||||
FileSystem.createDirectory(Path.join([workingDir, title]));
|
||||
|
||||
// Substitute the specified values into the Project.xml:
|
||||
@@ -231,8 +191,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"]);
|
||||
@@ -241,22 +201,17 @@ 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 workingDir = Sys.getCwd();
|
||||
var kissExpressLibPath = new Process("haxelib", ["libpath", "kiss-express"]).stdout.readAll().toString().trim();
|
||||
var workingDir = Sys.args().pop();
|
||||
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);
|
||||
makeFolderForNewProject(["externs"]);
|
||||
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissExpressLibPath, _, workingDir, title, pkg);
|
||||
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissExpressLibPath, _, workingDir, title, pkg);
|
||||
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"]);
|
||||
@@ -270,27 +225,31 @@ 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.getCwd();
|
||||
var workingDir = Sys.args().pop();
|
||||
var projectDir = Path.join([workingDir, title]);
|
||||
FileSystem.createDirectory(projectDir);
|
||||
|
||||
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, description, pkg);
|
||||
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, description, pkg);
|
||||
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, pkg);
|
||||
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissVscodeApiLibPath, _, workingDir, title, pkg);
|
||||
makeFolderForNewProject(["src"]);
|
||||
makeFolderForNewProject([".vscode"]);
|
||||
makeFileForNewProject([".gitignore"]);
|
||||
makeFileForNewProject([".vscodeignore"]);
|
||||
makeFileForNewProject(["README.md"]);
|
||||
makeFileForNewProject(["build.hxml"]);
|
||||
makeFileForNewProject(["package.json"]);
|
||||
{
|
||||
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(["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("-", "_");
|
||||
@@ -301,18 +260,16 @@ class Main {
|
||||
break;
|
||||
urlPatterns.push(nextPattern);
|
||||
}
|
||||
var workingDir = Sys.getCwd();
|
||||
var kissFirefoxLibPath = new Process("haxelib", ["libpath", "kiss-firefox"]).stdout.readAll().toString().trim();
|
||||
var workingDir = Sys.args().pop();
|
||||
var projectDir = Path.join([workingDir, title]);
|
||||
FileSystem.createDirectory(projectDir);
|
||||
|
||||
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, description, pkg);
|
||||
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, description, pkg);
|
||||
var makeFileForNewProject:haxe.Constraints.Function = _makeFileForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, pkg);
|
||||
var makeFolderForNewProject:haxe.Constraints.Function = _makeFolderForNewProject.bind(kissFirefoxLibPath, _, workingDir, title, 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"]);
|
||||
|
@@ -4,7 +4,6 @@ using Std;
|
||||
|
||||
import kiss.ReaderExp;
|
||||
import haxe.ds.Either;
|
||||
import haxe.ds.Option;
|
||||
import haxe.Constraints;
|
||||
import haxe.DynamicAccess;
|
||||
#if js
|
||||
@@ -77,15 +76,6 @@ 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)) {
|
||||
@@ -614,24 +604,6 @@ 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();
|
||||
}
|
||||
@@ -946,7 +918,7 @@ class Prelude {
|
||||
|
||||
static var shellCount = 0;
|
||||
|
||||
public static function shellExecute(script:String, shell:String):String {
|
||||
public static function shellExecute(script:String, shell:String) {
|
||||
#if ((sys || hxnodejs) && !frontend)
|
||||
if (shell.length == 0) {
|
||||
shell = if (Sys.systemName() == "Windows") "cmd /c" else "bash";
|
||||
@@ -965,14 +937,13 @@ class Prelude {
|
||||
if (Sys.systemName() != "Windows") tempScript = joinPath(Sys.getCwd(), tempScript);
|
||||
var parts = shell.split(" ").concat([tempScript]);
|
||||
var shell = parts.shift();
|
||||
return assertProcess(shell, parts);
|
||||
assertProcess(shell, parts);
|
||||
FileSystem.deleteFile(tempScript);
|
||||
} catch (e) {
|
||||
printStr('# Failing script:');
|
||||
printStr(script);
|
||||
printStr('#################');
|
||||
FileSystem.deleteFile(tempScript);
|
||||
print(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -998,9 +969,7 @@ class Prelude {
|
||||
#if js
|
||||
public static dynamic function makeAwaitLetDefaultCatch<TOut>(binding:String):PromiseHandler<Dynamic,TOut> {
|
||||
return function (reason:Dynamic):Promise<TOut> {
|
||||
var message = 'awaitLet $binding rejected promise: $reason';
|
||||
print(message);
|
||||
throw message;
|
||||
throw 'awaitLet $binding rejected promise: $reason';
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -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 :Null
|
||||
// or any of those with the first expression after -> or -+> prefixed by :Void
|
||||
function arrowSyntax(countingLambda:Bool, stream:Stream, k:HasReadTables) {
|
||||
var countVar = if (countingLambda) {
|
||||
_assertRead(stream, k);
|
||||
@@ -192,14 +192,10 @@ 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) {
|
||||
@@ -213,13 +209,10 @@ 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 or :Null. 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. 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]);
|
||||
|
@@ -42,7 +42,6 @@ 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.
|
||||
|
||||
@@ -54,7 +53,7 @@ class SpecialForms {
|
||||
}
|
||||
for (bodyExp in args) {
|
||||
switch(bodyExp.def) {
|
||||
case Symbol(name) if (lastArg != null && !unops.contains(name.substr(0, 2)) && !unops.contains(name.substr(name.length - 2, 2))):
|
||||
case Symbol(_) if (lastArg != null):
|
||||
KissError.warnFromExp(bodyExp, "This looks like an unused value");
|
||||
default:
|
||||
}
|
||||
@@ -233,7 +232,7 @@ class SpecialForms {
|
||||
};
|
||||
}
|
||||
|
||||
k.doc("deflocal", 2, 3, "(localVar <optional: &mut> <optional :type> <variable> <value>)");
|
||||
k.doc("deflocal", 2, 3, "(localVar <optional :type> <variable> <optional: &mut> <value>)");
|
||||
map["deflocal"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
|
||||
k.localVarCalls.push(wholeExp);
|
||||
k.localVarWarning();
|
||||
@@ -271,15 +270,12 @@ class SpecialForms {
|
||||
block;
|
||||
};
|
||||
|
||||
k.doc("lambda", 2, null, "(lambda <optional :Void or :Null> [<argsNames...>] <body...>)");
|
||||
k.doc("lambda", 2, null, "(lambda [<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;
|
||||
}
|
||||
@@ -472,11 +468,12 @@ class SpecialForms {
|
||||
};
|
||||
|
||||
// Type check syntax:
|
||||
k.doc("the", 2, 3, '(the <?package> <type> <value>)');
|
||||
k.doc("the", 2, 3, '(the <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');
|
||||
|
@@ -90,14 +90,6 @@ 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;
|
||||
}
|
||||
@@ -426,34 +418,6 @@ 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()) {
|
||||
|
@@ -1,25 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
(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")))
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"version": "4.3.1",
|
||||
"resolveLibs": "scoped"
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
# template
|
||||
{{description}}
|
@@ -1,5 +0,0 @@
|
||||
# @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()
|
@@ -1,5 +0,0 @@
|
||||
# @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')
|
@@ -1,12 +0,0 @@
|
||||
# @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()
|
@@ -1,3 +0,0 @@
|
||||
# @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
|
@@ -1,4 +0,0 @@
|
||||
# @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
|
@@ -1,4 +0,0 @@
|
||||
# @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
|
@@ -1,3 +0,0 @@
|
||||
-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
|
@@ -1,6 +0,0 @@
|
||||
# @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()
|
@@ -1,4 +0,0 @@
|
||||
# @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
|
@@ -1,3 +0,0 @@
|
||||
# @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
|
Reference in New Issue
Block a user