protected override object?Visit(Expression.Proc proc) { symbolTable.PushScope(ScopeKind.Proc); base.Visit(proc); symbolTable.PopScope(); return(null); }
protected override object?Visit(Expression.Proc proc) { Visit(proc.Signature); // NOTE: Parameters are already declared Visit(proc.Body); return(null); }
protected override Node?Visit(Expression.Proc proc) { if (dependencyMap.ProcDesugar.TryGetValue(proc, out var alt)) { return(Transform(alt)); } return(base.Visit(proc)); }
protected override Value?Visit(Expression.Proc proc) { // It it's cached, just return that if (compiledProcs.TryGetValue(proc, out var procVal)) { return(procVal); } WithSubcontext(() => { procVal = Builder.DefineProc(nameContext.NameOf(proc)); // Add it to the cache here to get ready for recursion compiledProcs.Add(proc, procVal); // For now we make every procedure public procVal.Visibility = Visibility.Public; // We need the return type Debug.Assert(proc.Signature.Return != null); var returnType = EvaluateType(proc.Signature.Return); procVal.Return = TranslateToLirType(returnType); // We need to compile parameters foreach (var param in proc.Signature.Parameters) { // Get the parameter type, define it in the Lir code var paramType = EvaluateType(param.Type); var lirParamType = TranslateToLirType(paramType); var paramValue = Builder.DefineParameter(lirParamType); // We make parameters mutable by making them allocate space on the stack and refer to that space var paramSpace = Builder.Alloc(lirParamType); // Copy the initial value Builder.Store(paramSpace, paramValue); if (param.Name != null) { // It has a symbol, we store the allocated space associated var symbol = SymbolTable.DefinedSymbol(param); context.Variables.Add(symbol, paramSpace); } } // Now we can compile the body Visit(proc.Body); // Add a return, if there's none and the return-type is unit if (!Builder.CurrentBasicBlock.EndsInBranch && returnType.Equals(Semantic.Types.Type.Unit)) { Builder.Ret(); } }); Debug.Assert(procVal != null); return(procVal); }
protected override object?Visit(Expression.Proc proc) { Visit(proc.Signature); // Evaluate parameter types, assign their return types foreach (var param in proc.Signature.Parameters) { var symbol = (Symbol.Var)System.SymbolTable.DefinedSymbol(param); symbol.Type = System.EvaluateType(param.Type); } // Deduce return type Debug.Assert(proc.Signature.Return != null); var returnType = System.EvaluateType(proc.Signature.Return); // We type-check with this return type WithCurrentProcReturnType(returnType, proc.Signature, () => Visit(proc.Body)); return(null); }
protected override Node?Visit(Expression.Proc proc) => new Expression.Proc( proc.ParseTreeNode, (Expression.ProcSignature)Transform(proc.Signature), DesugarProcBody(proc.Body));
protected override object?Visit(Expression.Proc proc) { base.Visit(proc); var procType = (Type.Proc)System.TypeOf(proc); var dependency = procType.GetDependency(); if (dependency != null) { /* * Desugar * proc(dependee args..., dependent args..., independent args...) -> Ret { * body * } * Into * proc(dependee args...) -> type { * struct { * const f = proc(dependent args..., independent args...) -> Ret { * body * }; * } * } */ var result = new Expression.Proc( null, new Expression.ProcSignature( null, dependency.DependeeIndices .Select(i => proc.Signature.Parameters[i]) .ToArray(), new Expression.Identifier(null, "type")), new Expression.Block( null, new Statement[] { }, new Expression.StructType( null, new Syntax.Token(new Text.Span(), Syntax.TokenType.KwStruct, "struct"), new Expression.StructType.Field[] { }, new Statement[] { new Declaration.Const( null, "f", null, new Expression.Proc( null, new Expression.ProcSignature( null, dependency.DependentIndices .Concat(dependency.IndependentIndices) .Select(i => proc.Signature.Parameters[i]) .ToArray(), proc.Signature.Return), proc.Body)) }))); result = (Expression.Proc) new Desugaring().Desugar(result); DependencyMap.ProcDesugar.Add(proc, result); } return(null); }