예제 #1
0
 public override void Emit(TranspilerStream stream)
 {
     stream.Write(Compiler.Prefix);
     stream.Write("Bool(!(");
     Value.Emit(stream);
     stream.Write(").val)");
 }
예제 #2
0
        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__();}}");
        }
예제 #3
0
 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(')');
 }
예제 #4
0
        public void EmitForwardDecl(TranspilerStream stream)
        {
            GenerateConstructor();

            stream.Write("struct ");
            stream.Write(Compiler.Prefix);
            stream.Write(Id.Text);
            stream.WriteLine(';');
        }
예제 #5
0
 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(')');
 }
예제 #6
0
        public void EmitDecl(TranspilerStream stream)
        {
            stream.Write("struct ");
            stream.Write(Compiler.Prefix);
            stream.Write(Id.Text);

            stream.WriteLine('{');
            Body?.EmitDecl(stream);
            stream.WriteLine("};\n");
        }
예제 #7
0
 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(')');
 }
예제 #8
0
 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);
 }
예제 #9
0
        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('}');
        }
예제 #10
0
        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("}");
        }
예제 #11
0
 private void EmitReturnType(TranspilerStream stream)
 {
     if (ReturnType == null)
     {
         stream.Write("void");
     }
     else
     {
         ReturnType.Emit(stream);
     }
 }
예제 #12
0
        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;
        }
예제 #13
0
        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(')');
        }
예제 #14
0
        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(';');
        }
예제 #15
0
        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(';');
        }
예제 #16
0
 public void EmitSpec(TranspilerStream stream)
 {
     stream.Write(Compiler.Prefix);
     stream.Write(Id.Text);
 }
예제 #17
0
 public override void Emit(TranspilerStream stream)
 {
     // Immutable borrow => const __ZERM__Type&
     stream.Write(Compiler.Prefix);
     stream.Write(Id.Text);
 }
예제 #18
0
 public override void Emit(TranspilerStream stream)
 {
     Left.Emit(stream);
     stream.Write('.');
     Right.Emit(stream);
 }
예제 #19
0
 private void EmitPrototype(TranspilerStream stream)
 {
     EmitReturnType(stream);
     stream.Write(' ');
     EmitIdAndParams(stream);
 }
예제 #20
0
        public override void Emit(TranspilerStream stream)
        {
            var varDecl = Block.FindVar(this, throws: true) !.Value;

            stream.Write(varDecl.CName);
        }
예제 #21
0
        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(")");
            }
        }
예제 #22
0
        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();
            }
        }