private void EmitIdAndParams(TranspilerStream stream) { // Append __ZERM__ to the front of the identifier // and also a return suffix because our languages counts // return type in a function signature. stream.Write(Compiler.Prefix); stream.Write(Id.Text); stream.Write("__"); ReturnType?.Emit(stream); stream.Write('('); var isFirst = true; foreach (var param in Params) { if (!isFirst) { stream.Write(','); } else { isFirst = false; } param.Emit(stream); } stream.Write(')'); }
public override void Emit(TranspilerStream stream) { stream.Write(Compiler.Prefix); stream.Write("Bool(!("); Value.Emit(stream); stream.Write(").val)"); }
public void Emit(TranspilerStream stream) { if (Body == null) { return; } // Emit a preamble to wrap C++: stream.Write( $@"#include <iostream> #include <gmp.h> #include <math.h> #include <string> "); Body.EmitDecl(stream); Body.EmitImpl(stream); // Check that there is a main function in the global scope. var mainFn = Body.FindFn(new FnCall(Body, new Token(TokenId.Id, "Main", 0, 0))); if (mainFn == null) { throw new CompileError("No Main function found"); } stream.Write( $"\nint main(){{{Compiler.Prefix}Main__();}}"); }
public override void Emit(TranspilerStream stream) { stream.WriteLine("else{"); Body.EmitDecl(stream); Body.EmitImpl(stream); stream.WriteLine("}"); }
public void EmitForwardDecl(TranspilerStream stream) { GenerateConstructor(); stream.Write("struct "); stream.Write(Compiler.Prefix); stream.Write(Id.Text); stream.WriteLine(';'); }
public override void Emit(TranspilerStream stream) { // C++ string wrapper: // __ZERM__String(<string>) stream.Write(Compiler.Prefix); stream.Write("String("); stream.Write(Value.Text); stream.Write(')'); }
public override void Emit(TranspilerStream stream) { // C++ boolean wrapper: // __ZERM__Bool(true) // __ZERM__Bool(false) stream.Write(Compiler.Prefix); stream.Write("Bool("); stream.Write(Value.Text.ToLowerInvariant()); stream.Write(')'); }
public void EmitDecl(TranspilerStream stream) { stream.Write("struct "); stream.Write(Compiler.Prefix); stream.Write(Id.Text); stream.WriteLine('{'); Body?.EmitDecl(stream); stream.WriteLine("};\n"); }
public override void Emit(TranspilerStream stream) { stream.Write(Compiler.Prefix); stream.Write("Bool("); Left.Emit(stream); stream.Write(".val ||"); Right.Emit(stream); stream.Write(".val"); stream.Write(')'); }
public void Emit(TranspilerStream stream) { if (PassedBy == PassedBy.ImmutableBorrow) { stream.Write("const "); } TypeSpec.Emit(stream); stream.Write("& "); stream.Write(Compiler.Prefix); stream.Write(Id.Text); }
private void EmitReturnType(TranspilerStream stream) { if (ReturnType == null) { stream.Write("void"); } else { ReturnType.Emit(stream); } }
public void EmitDecl(TranspilerStream stream) { // If this is the global block, don't allow statements. if (Parent == null && Stmts.Count > 0) { throw new CompileError(Stmts.First().Token, $"Statements not allowed in the global block"); } var typeDeclIds = new HashSet <string>(); foreach (var decl in TypeDecls) { typeDeclIds.Add(decl.Id.Text); decl.EmitForwardDecl(stream); } // Some metafunctions should be emitted within the type declaration // itself. Emit those now. if (ParentDecl is TypeDecl) { foreach (var stmt in Stmts) { if (stmt is ExprStmt expr) { if (expr.Expr is FnCall call) { Metafunctions.Emit(stream, call, forward: true); } } } } foreach (var decl in TypeDecls) { decl.EmitDecl(stream); } foreach (var decl in FnDecls) { if (typeDeclIds.Contains(decl.Id.Text) && !decl.IsGeneratedConstructor) { throw new CompileError(decl.Id, $"Type already declared in this scope with ID '{decl.Id.Text}'"); } decl.EmitForwardDecl(stream); } }
public override void Emit(TranspilerStream stream) { // Check that we are in a fn decl. if (Block.ParentDecl is FnDecl fn) { if (fn.ReturnType == null) { if (Value != null) { throw new CompileError(Value.Token, "Cannot return expression from 'void' procedure"); } } else { if (Value == null) { throw new CompileError(Token, "Function must return a value"); } else if (Value.TypeDecl != fn.Block.FindType(fn.ReturnType)) { throw new CompileError(Value.Token, "Expression does not match function's return type"); } } } else { throw new CompileError(Token, "Cannot return from outside a function"); } // Check that we are returning something that can be returned. if (Value is VarExpr varExpr) { if (!varExpr.VarDecl.Returnable) { throw new CompileError(Value.Token, "Cannot return a borrowed variable"); } } stream.Write("return "); Value?.Emit(stream); stream.WriteLine(';'); }
public void EmitImpl(TranspilerStream stream) { EmitReturnType(stream); stream.Write(' '); if (Block.ParentDecl is TypeDecl type) { // Member function type.EmitSpec(stream); stream.Write("::"); } EmitIdAndParams(stream); stream.WriteLine('{'); Body?.EmitImpl(stream); stream.WriteLine('}'); }
public override void Emit(TranspilerStream stream) { if (LitType == NumLiteralType.Int) { // _ZRM_Int("str", base) stream.Write(Compiler.Prefix); stream.Write("Int(\""); stream.Write(Value.Text.Replace("_", "")); stream.Write("\",10)"); } else if (LitType == NumLiteralType.Rat) { // _ZRM_Rat("str", base) var text = Value.Text.Replace("r", ""); if (text.Contains('.')) { // e.g. 0.1, index of '.' is 1, so 10^1 goes on the denom. var denom = "1" + new string('0', text.IndexOf('.')); text = text.Replace(".", "") + "/" + denom; } stream.Write(Compiler.Prefix); stream.Write("Rat(\""); stream.Write(text); stream.Write("\",10)"); } else if (LitType == NumLiteralType.Float32) { // _ZRM_Float32(val) stream.Write(Compiler.Prefix); stream.Write("Float32("); var text = Value.Text.Replace("_", ""); if (!text.Contains('.')) { text += ".0"; } stream.Write(text.Replace("f", "")); stream.Write("f)"); } else if (LitType == NumLiteralType.Int32) { // _ZRM_Int32(val) throw new NotImplementedException(); } else { throw new NotImplementedException(); } }
public override void Emit(TranspilerStream stream) { if (Condition.TypeDecl != Block.Global().FindType("Bool")) { throw new CompileError(Condition.Token, "If conditional must be a boolean expression"); } stream.Write("if(!("); Condition.Emit(stream); stream.Write(".val"); stream.WriteLine(")){"); Body.EmitDecl(stream); Body.EmitImpl(stream); stream.WriteLine("}"); }
public override void Emit(TranspilerStream stream) { // Declaration of a variable. var typeSpec = new SimpleTypeSpec(Value.TypeDecl.Id); var decl = new VarDecl(Block, Id, typeSpec, Mutable ? VarAccess.MutableLocal : VarAccess.ImmutableLocal); if (!Mutable) { stream.Write("const "); } decl.TypeSpec.Emit(stream); stream.Write(' '); stream.Write(decl.CName); stream.Write('='); Value.Emit(stream); stream.WriteLine(';'); Block.Vars[decl.Id.Text] = decl; }
public override void Emit(TranspilerStream stream) { var decl = Block.FindVar( new VarExpr(Block, Id), throws: false ); if (!decl.HasValue) { throw new CompileError(Id, "Reassignment of undeclared variable"); } if (!decl.Value.Mutable) { throw new CompileError(Id, "Reassignment of immutable variable"); } // Reassign the value. stream.Write(decl.Value.CName); stream.Write('='); Value.Emit(stream); stream.WriteLine(';'); }
public void EmitImpl(TranspilerStream stream) { // If this is the global block, don't allow statements. if (Parent == null && Stmts.Count > 0) { throw new CompileError(Stmts.First().Token, $"Statements not allowed in the global block"); } foreach (var decl in TypeDecls) { decl.EmitImpl(stream); } foreach (var decl in FnDecls) { decl.EmitImpl(stream); } foreach (var stmt in Stmts) { stmt.Emit(stream); } }
public abstract void Emit(TranspilerStream stream);
public override void Emit(TranspilerStream stream) { Expr.Emit(stream); stream.WriteLine(";"); }
public override void Emit(TranspilerStream stream) { // Immutable borrow => const __ZERM__Type& stream.Write(Compiler.Prefix); stream.Write(Id.Text); }
public override void Emit(TranspilerStream stream) { Left.Emit(stream); stream.Write('.'); Right.Emit(stream); }
public void EmitForwardDecl(TranspilerStream stream) { EmitPrototype(stream); stream.WriteLine(';'); }
public override void Emit(TranspilerStream stream) { var varDecl = Block.FindVar(this, throws: true) !.Value; stream.Write(varDecl.CName); }
private void EmitPrototype(TranspilerStream stream) { EmitReturnType(stream); stream.Write(' '); EmitIdAndParams(stream); }
public void EmitSpec(TranspilerStream stream) { stream.Write(Compiler.Prefix); stream.Write(Id.Text); }
public override void Emit(TranspilerStream stream) { if (Id.Text.StartsWith('#')) { Metafunctions.Emit(stream, this, forward: false); } else { // Try to find a matching function: FnDecl?fn = null; if (ParentAccess != null) { fn = ParentAccess.Left.TypeDecl.Block.FindFn(this); } else { fn = Block.FindFn(this); } fn = fn ?? throw new CompileError(Token, "Cannot find matching function"); // Verify that the expressions passed into the function // match the pass-by-tyep of each argument. for (int i = 0; i < fn.Params.Count; i++) { var param = fn.Params[i]; var arg = Args[i]; if (!param.CompatibleWith(arg, out var errorMessage)) { throw new CompileError(arg.Token, errorMessage); } } stream.Write(Compiler.Prefix); stream.Write(Id.Text); // Functions also have suffixes relating to return type: stream.Write("__"); fn.ReturnType?.Emit(stream); // Write function arguments: stream.Write('('); var actualArgs = new Expr[Args.Count]; // Process as named args to get a new order of arguments to pass in. var namedArgsStarted = false; var index = 0; var namedArgs = new HashSet <string>(); foreach (var arg in Args) { if (arg.NamedArg.HasValue) { namedArgsStarted = true; if (!namedArgs.Add(arg.NamedArg.Value.Text)) { throw new CompileError("Named argument already specified"); } // Find the matching named parameter. var paramIndex = fn.Params.FindIndex( x => x.Id.Text == arg.NamedArg.Value.Text); if (paramIndex == -1) { throw new CompileError("Named argument not found"); } else { if (actualArgs[paramIndex] != null) { throw new CompileError("Argument already specified"); } actualArgs[paramIndex] = arg; } } else { if (namedArgsStarted) { throw new CompileError( "Positional arguments cannot follow named arguments"); } actualArgs[index] = arg; index += 1; } } // Check for missing arguments. if (actualArgs.Any(x => x == null)) { throw new CompileError("Missing one or more required arguments"); } // Process the generated array of positional args. var firstArg = true; foreach (var arg in actualArgs) { if (!firstArg) { stream.Write(','); } else { firstArg = false; } arg.Emit(stream); } stream.Write(")"); } }
public void EmitImpl(TranspilerStream stream) { Body?.EmitImpl(stream); }