generic function parameters

This commit is contained in:
2022-06-28 04:40:13 +00:00
parent 698e6cbf39
commit e046b4462e
6 changed files with 46 additions and 6 deletions

View File

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

View File

@@ -109,14 +109,31 @@ class Helpers {
};
}
// TODO generic type parameter declarations
public static function makeFunction(?name:ReaderExp, returnsValue:Bool, argList:ReaderExp, body:List<ReaderExp>, k:KissState, formName:String):Function {
public static function makeTypeParam(param:ReaderExp, ?constraints:Array<ComplexType> = 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 <GenericTypeName> or :<Constraint> <GenericTypeName>");
}
}
public static function makeFunction(?name:ReaderExp, returnsValue:Bool, argList:ReaderExp, body:List<ReaderExp>, k:KissState, formName:String, typeParams:Array<ReaderExp>):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
};
}

View File

@@ -307,7 +307,8 @@ class Kiss {
b.list([]),
[topLevelBegin],
k,
"function")),
"function",
[])),
pos: topLevelBegin.macroPos()
});
}

View File

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

View File

@@ -23,5 +23,6 @@ enum ReaderExpDef {
UnquoteList(exp:ReaderExp); // ,@[exp]
ListEatingExp(exps:Array<ReaderExp>); // [::exp exp ...exps exp]
ListRestExp(name:String); // ...exps or ...
TypeParams(types:Array<ReaderExp>); // <>[T :Constraint U :Constraint1 :Constraint2 V]
None; // not an expression, i.e. (#unless falseCondition exp)
}

View File

@@ -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<ReaderExp>, k:KissState) {