コード例 #1
0
ファイル: Codegen.cs プロジェクト: LPeter1997/YoakkeLang
 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);
 }