private int GenerateLambda(AstLambda ast) { // create empty lambda function. // there are no any arguments var lambda = new CodeGenerator(ast.ArgList.Length); // update list of arguments lambda.DefineArguments(ast.ArgList); /// R(A) := closure(KPROTO[Bx], R(A), ... , R(A + n)) var temp = -1; // now generate the code, and get target register foreach (var v in ast.BodyExpression) { temp = lambda.Generate(v.AsAST()); //if (tgt != temp) // lambda.AddAB(OpCode.MOVE, temp, (byte)tgt); } lambda.GenerateReturn(temp); // now lets create template from dummy lambda var template = lambda.GetTemplate(); // ----------------------------------------- // now generate code for current function // ----------------------------------------- temp = Push(); var closureId = DefineLiteral(new Value(template)); AddABX(OpCode.CLOSURE, temp, closureId); template.ResultIdx = temp; return(temp); }
// (let () ...) public static AST Expand(Syntax stx, Environment env) { var list = stx.AsLinkedList <Value>(); var argc = GetArgsCount(list); AssertArgsMinimum("let", "arity mismatch", 2, argc, list, stx); var keyword = list[0].AsSyntax(); // let arguments var arguments = list[1].AsSyntax(); // let arguments if (!arguments.IsExpression) { throw SchemeError.SyntaxError("let", "bad syntax (missing name or binding pairs)", stx); } var localEnv = ArgumentsParser.ParseLet(stx, arguments.AsLinkedList <Value>(), env); AST lambda = new AstLambda(stx, keyword, localEnv, AstBuilder.ExpandListElements(list, 2, localEnv)); var result = new LinkedList <Value>(); result.AddLast(lambda.ToValue()); foreach (var v in localEnv) { if (v is ArgumentBinding) { var arg = v as ArgumentBinding; if (arg.ArgType == ArgumentBinding.Type.Required) { result.AddLast(new Value(arg.Initializer)); } } } return(new AstApplication(stx, result)); }
void InstrumentFunction(AstLambda lambda) { if (lambda.Source == null) { InstrumentBlock(ref lambda.Body); return; } var idx = _owner.LastIndex++; var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement)); call.Args.Add(new AstNumber(idx)); lambda.Body.Insert(0) = new AstSimpleStatement(call); _owner.GetForFile(lambda.Source) .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Function, idx, lambda.Start, lambda.End)); var input = new StructList <AstNode>(); input.TransferFrom(ref lambda.Body); lambda.Body.Reserve(input.Count * 2 - 1); lambda.Body.Add(input[0]); for (var i = 1; i < input.Count; i++) { var ii = input[i]; if (ShouldStatementCover(ii)) { if (i != 1) { idx = _owner.LastIndex++; call = new AstCall(new AstSymbolRef(_owner.FncNameStatement)); call.Args.Add(new AstNumber(idx)); lambda.Body.Add(new AstSimpleStatement(call)); } _owner.GetForFile(ii.Source !) .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, ii.Start, ii.End)); } ii = Transform(ii); lambda.Body.Add(ii); } }
private Expression CompileLambda(AstLambda l) { var ps = l.ParameterList.Parameters; // The parser currently doesn't parse default values so this shouldn't happen, // so this check is for if the parser is changed in the future if (ps.Any(p => p.OptionalValue != null)) { Error(l.Source, ErrorCode.E0000, "Lambda parameters cannot have default values"); } if (ps.Count > 0) { var hasType = ps[0].OptionalType != null; if (ps.Any(p => (p.OptionalType != null) != hasType)) { Error(l.Source, ErrorCode.E0748, "Inconsistent lambda parameter usage; all parameter types must either be explicit or implicit"); } } // We defer compiling the lambda until it is implicitly cast to a delegate type return(new UncompiledLambda(l.Source, l)); }
// (define x ...) // (define (x) ...) public static AST Expand(Syntax stx, Environment env) { var list = stx.AsLinkedList <Value>(); var argc = GetArgsCount(list); AssertArgsMinimum("define", "arity mismatch", 2, argc, list, stx); var def_stx = list[0].AsSyntax(); // define var var_stx = list[1].AsSyntax(); // () if (var_stx.IsIdentifier) { AssertArgsMaximum("define", "arity mismatch", 2, argc, list, stx); var val_stx = list[2].AsSyntax(); // ---------------------------------------------------------------- // identifier aka: (define x ...) // ---------------------------------------------------------------- var value = AstBuilder.ExpandInternal(val_stx, env); var var_id = var_stx.AsIdentifier(); var binding = env.LookupAst(var_id); if (binding == null) { // Global variable return(new AstSet(stx, var_stx, value, -1, -1, -1)); } else if (binding is UpBinding) { // Up-value variable var ubind = binding as UpBinding; return(new AstSet(stx, var_stx, value, binding.VarIdx, ubind.UpEnvIdx, ubind.UpVarIdx)); } else { // Local variable return(new AstSet(stx, var_stx, value, binding.VarIdx, 0, 0)); } } else if (var_stx.IsExpression) { // ---------------------------------------------------------------- // identifier aka: (define (x ...) ...) as result lambda expression // ---------------------------------------------------------------- var args_list = var_stx.AsLinkedList <Value>(); var newenv = ArgumentsParser.ParseLambda(stx, args_list, env); var lambda_body = AstBuilder.ExpandListElements(list, 2, newenv); var lambda = new AstLambda(stx, def_stx, newenv, lambda_body); var identifier_stx = args_list[0].AsSyntax(); var identifier = identifier_stx.AsIdentifier(); var binding = env.LookupAst(identifier); if (binding == null) { /// Global variable return(new AstSet(stx, var_stx, lambda, -1, -1, -1)); } else if (binding is UpBinding) { /// Up-value variable var ubind = binding as UpBinding; return(new AstSet(stx, var_stx, lambda, binding.VarIdx, ubind.UpEnvIdx, ubind.UpVarIdx)); } else { /// Local variable return(new AstSet(stx, var_stx, lambda, binding.VarIdx, 0, 0)); } } else { throw SchemeError.ArgumentError("define", "symbol? or list?", var_stx); } }
public UncompiledLambda(Source src, AstLambda astLambda) : base(src) { AstLambda = astLambda; }
void InstrumentFunction(AstLambda lambda) { if (lambda is AstArrow arrow) { if (arrow.Body.Count == 1 && arrow.Body.Last.IsExpression()) { var original = arrow.Body[0]; arrow.Body[0] = new AstBlock(original) { Body = new() { new AstReturn(original) { Value = original } } }; } } if (lambda.Source == null) { InstrumentBlock(ref lambda.Body); return; } var idx = _owner.LastIndex++; var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement)); call.Args.Add(new AstNumber(idx)); lambda.Body.Insert(0) = new AstSimpleStatement(call); _owner.GetForFile(lambda.Source) .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Function, idx, lambda.Start, lambda.End)); var input = new StructList <AstNode>(); input.TransferFrom(ref lambda.Body); lambda.Body.Reserve(input.Count * 2 - 1); lambda.Body.Add(input[0]); for (var i = 1; i < input.Count; i++) { var ii = input[i]; if (ShouldStatementCover(ii)) { if (i != 1) { idx = _owner.LastIndex++; call = new AstCall(new AstSymbolRef(_owner.FncNameStatement)); call.Args.Add(new AstNumber(idx)); lambda.Body.Add(new AstSimpleStatement(call)); } _owner.GetForFile(ii.Source !) .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, ii.Start, ii.End)); } ii = Transform(ii); lambda.Body.Add(ii); } } AstNode InstrumentExpression(AstNode node) { if (node is AstSequence) { return(node); } if (node.Source == null) { return(node); } var res = new AstSequence(node); var idx = _owner.LastIndex++; var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement)); call.Args.Add(new AstNumber(idx)); res.Expressions.Add(call); res.Expressions.Add(node); _owner.GetForFile(node.Source) .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, node.Start, node.End)); return(res); } void InstrumentBlock(ref StructList <AstNode> block, bool seq = false) { var input = new StructList <AstNode>(); input.TransferFrom(ref block); block.Reserve(input.Count * 2); for (var i = 0; i < input.Count; i++) { var ii = input[i]; if (ShouldStatementCover(ii)) { var idx = _owner.LastIndex++; var call = new AstCall(new AstSymbolRef(_owner.FncNameStatement)); call.Args.Add(new AstNumber(idx)); if (seq) { block.Add(call); } else { block.Add(new AstSimpleStatement(call)); } _owner.GetForFile(ii.Source !) .AddInfo(new InstrumentedInfo(InstrumentedInfoType.Statement, idx, ii.Start, ii.End)); } ii = Transform(ii); block.Add(ii); } }
public void WriteLambda(AstLambda a) { Write(a.Source); WriteParameterList(a.ParameterList); Write(a.Body); }