1 Commits

Author SHA1 Message Date
2ea0066d32 try cp on build.hxml 2025-01-25 13:39:36 -06:00
30 changed files with 191 additions and 603 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,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')

View File

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

View File

@@ -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")

View File

@@ -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

View File

@@ -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) {

View File

@@ -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>();

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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}"))))

View File

@@ -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);

View File

@@ -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"]);

View File

@@ -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';
};
}

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 :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]);

View File

@@ -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');

View File

@@ -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()) {

View File

@@ -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();
}
}

View File

@@ -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")))

View File

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

View File

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

View File

@@ -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()

View File

@@ -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')

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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