From e046b4462eee302d541d42566712637d239466ae Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Tue, 28 Jun 2022 04:40:13 +0000 Subject: [PATCH] generic function parameters --- src/kiss/FieldForms.hx | 10 +++++++++- src/kiss/Helpers.hx | 24 +++++++++++++++++++++--- src/kiss/Kiss.hx | 3 ++- src/kiss/Reader.hx | 12 ++++++++++++ src/kiss/ReaderExp.hx | 1 + src/kiss/SpecialForms.hx | 2 +- 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/kiss/FieldForms.hx b/src/kiss/FieldForms.hx index bdbeb9d..6d8f382 100644 --- a/src/kiss/FieldForms.hx +++ b/src/kiss/FieldForms.hx @@ -124,6 +124,13 @@ class FieldForms { var returnsValue = !isVoid(args[0]); var wasInStatic = k.inStaticFunction; + var typeParams = switch (args[1].def) { + case TypeParams(p): + args.splice(1, 1); + p; + default: + []; + } var f:Field = { name: name, @@ -135,7 +142,8 @@ class FieldForms { args[1], args.slice(2), k.forStaticFunction(inStaticFunction), - formName)), + formName, + typeParams)), pos: wholeExp.macroPos() }; diff --git a/src/kiss/Helpers.hx b/src/kiss/Helpers.hx index e9b195a..afb415f 100644 --- a/src/kiss/Helpers.hx +++ b/src/kiss/Helpers.hx @@ -109,14 +109,31 @@ class Helpers { }; } - // TODO generic type parameter declarations - public static function makeFunction(?name:ReaderExp, returnsValue:Bool, argList:ReaderExp, body:List, k:KissState, formName:String):Function { + public static function makeTypeParam(param:ReaderExp, ?constraints:Array = null):TypeParamDecl { + if (constraints == null) constraints = []; + switch (param.def) { + case Symbol(name): + return { + name: name, + constraints: constraints + }; + case TypedExp(type, param): + constraints.push(parseComplexType(type)); + return makeTypeParam(param, constraints); + default: + throw KissError.fromExp(param, "expected or : "); + } + } + + public static function makeFunction(?name:ReaderExp, returnsValue:Bool, argList:ReaderExp, body:List, k:KissState, formName:String, typeParams:Array):Function { var funcName = if (name != null) { varName(formName, name, "function"); } else { ""; }; + var params = [for (p in typeParams) makeTypeParam(p)]; + var numArgs = 0; // Once the &opt meta appears, all following arguments are optional until &rest var opt = false; @@ -218,7 +235,8 @@ class Helpers { return { ret: if (name != null) Helpers.explicitType(name) else null, args: args, - expr: expr + expr: expr, + params: params }; } diff --git a/src/kiss/Kiss.hx b/src/kiss/Kiss.hx index 1325960..7895f59 100644 --- a/src/kiss/Kiss.hx +++ b/src/kiss/Kiss.hx @@ -307,7 +307,8 @@ class Kiss { b.list([]), [topLevelBegin], k, - "function")), + "function", + [])), pos: topLevelBegin.macroPos() }); } diff --git a/src/kiss/Reader.hx b/src/kiss/Reader.hx index d88c766..ba9e5bb 100644 --- a/src/kiss/Reader.hx +++ b/src/kiss/Reader.hx @@ -39,6 +39,8 @@ class Reader { // and also handles string interpolation cases like "${exp}moreString" readTable["{"] = (stream:Stream, k) -> CallExp(Symbol("begin").withPos(stream.position()), readExpArray(stream, "}", k)); + readTable["<>["] = (stream, k) -> TypeParams(readExpArray(stream, "]", k)); + readTable['"'] = readString.bind(_, _, false); readTable["#"] = readRawString; @@ -506,6 +508,16 @@ class Reader { ].join(" "); str += ']'; str; + case TypeParams(exps): + // <>[T1 T2 T3] + var str = '<>['; + str += [ + for (exp in exps) { + exp.def.toString(); + } + ].join(" "); + str += ']'; + str; case StrExp(s): // "literal" '"$s"'; diff --git a/src/kiss/ReaderExp.hx b/src/kiss/ReaderExp.hx index 6c32688..26c50db 100644 --- a/src/kiss/ReaderExp.hx +++ b/src/kiss/ReaderExp.hx @@ -23,5 +23,6 @@ enum ReaderExpDef { UnquoteList(exp:ReaderExp); // ,@[exp] ListEatingExp(exps:Array); // [::exp exp ...exps exp] ListRestExp(name:String); // ...exps or ... + TypeParams(types:Array); // <>[T :Constraint U :Constraint1 :Constraint2 V] None; // not an expression, i.e. (#unless falseCondition exp) } diff --git a/src/kiss/SpecialForms.hx b/src/kiss/SpecialForms.hx index 65e20c2..9e00e06 100644 --- a/src/kiss/SpecialForms.hx +++ b/src/kiss/SpecialForms.hx @@ -230,7 +230,7 @@ class SpecialForms { default: true; } - EFunction(FAnonymous, Helpers.makeFunction(null, returnsValue, args[0], args.slice(1), k, "lambda")).withMacroPosOf(wholeExp); + EFunction(FAnonymous, Helpers.makeFunction(null, returnsValue, args[0], args.slice(1), k, "lambda", [])).withMacroPosOf(wholeExp); }; function forExpr(formName:String, wholeExp:ReaderExp, args:Array, k:KissState) {