Esempio n. 1
0
        void CompileCall(CallExpression call)
        {
            // Try to resolve the function
            Symbol sym;
            var    callNameExpr = call.Target as NameExpression;

            if (callNameExpr != null)
            {
                // Check if the target function is in scope
                if (!Table.FindSymbol(callNameExpr.Name, out sym))
                {
                    // The function is undefined or not in scope
                    // Throw an exception
                    throw LoreException.Create(Location).Describe($"Attempt to call undefined function '{callNameExpr.Name}'");
                }

                // Parse the arguments
                var args = new LLVMValueRef [Math.Max(call.Arguments.Count, 0)];
                for (var i = 0; i < args.Length; i++)
                {
                    call.Arguments.Arguments [i].Visit(this);
                    args [i] = Stack.Pop().Value;
                }

                // The function is in scope
                var callResult = LLVM.BuildCall(Builder, sym.Value, args, "tmpcall");
                Stack.Push(Symbol.CreateAnonymous(callResult));
            }
            else
            {
                throw LoreException.Create(Location).Describe($"Attempt to call something that is everything but a function.");
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Pops a scope.
 /// </summary>
 /// <returns>The scope.</returns>
 public void PopScope()
 {
     if (Scopes.Count <= 1)
     {
         throw LoreException.Create().Describe("Attempt to leave global scope.").Describe("This is a compiler bug.");
     }
     Scopes.Pop();
 }
Esempio n. 3
0
        AssignStatement ParseAssignStatement()
        {
            var stmt = AssignStatement.Create(unit.Location);

            // Parse identifiers
            while (!unit.Match(LoreToken.Operator, "="))
            {
                // Parse name
                var ident = ParseName();
                var name  = NamedParameter.Create(ident);

                // Parse type
                if (unit.Accept(LoreToken.Colon))
                {
                    name.SetType(ParseName());
                }

                // Add the named parameter to the identifiers
                stmt.AddIdentifier(name);

                // Try parsing another identifier
                if (!unit.Match(LoreToken.Operator, "="))
                {
                    unit.Expect(LoreToken.Comma);
                }
            }
            unit.Expect(LoreToken.Operator, "=");

            // Parse expressions
            do
            {
                var expr = ParseExpression();
                stmt.AddExpression(expr);
            } while (unit.Accept(LoreToken.Comma));

            // Verify that all identifiers are satisfied
            var pluralizeExpression = stmt.ExpressionCount > 1 ? "s" : string.Empty;
            var pluralizeIdentifier = stmt.IdentifierCount > 1 ? "s" : string.Empty;

            if (stmt.IdentifierCount > stmt.ExpressionCount)
            {
                var count = stmt.IdentifierCount - stmt.ExpressionCount;
                var pluralizeDifference = count > 1 ? "s" : string.Empty;
                throw LoreException.Create(stmt.Location)
                      .Describe($"Attempt to assign {stmt.ExpressionCount} expression{pluralizeExpression} to {stmt.IdentifierCount} identifier{pluralizeIdentifier}.")
                      .Resolve($"Add more expressions or remove {count} identifier{pluralizeDifference}.");
            }
            if (stmt.IdentifierCount < stmt.ExpressionCount)
            {
                var count = stmt.ExpressionCount - stmt.IdentifierCount;
                var pluralizeDifference = count > 1 ? "s" : string.Empty;
                throw LoreException.Create(stmt.Location)
                      .Describe($"Attempt to assign {stmt.ExpressionCount} expression{pluralizeExpression} to {stmt.IdentifierCount} identifier{pluralizeIdentifier}.")
                      .Resolve($"Discard {count} expression{pluralizeDifference} by using the _ operator.");
            }

            return(stmt);
        }
Esempio n. 4
0
 public void Capture(string name)
 {
     if (Captures.Contains(name))
     {
         throw LoreException.Create()
               .Describe($"Symbol '{name}' was captured multiple times.")
               .Resolve($"Capture the symbol just once.");
     }
     Captures.Add(name);
 }
Esempio n. 5
0
        /// <summary>
        /// Create a new instance of the <see cref="Capture"/> class.
        /// </summary>
        /// <param name="unit">Unit.</param>
        /// <param name="lex">Lex.</param>
        public static Capture Create(ParsingUnit unit, Lexeme <LoreToken> lex)
        {
            if (lex.Is(LoreToken.Identifier))
            {
                return(new Capture(lex.Value, capturesAll: false));
            }
            if (lex.Is(LoreToken.Operator) && lex.Is("="))
            {
                return(new Capture(lex.Value, capturesAll: true));
            }

            // Invalid capture
            throw LoreException.Create(unit.Location).Describe($"Not a capture: '{lex.Value}' ({lex.Token})");
        }
Esempio n. 6
0
        IntegerExpression ParseInteger()
        {
            var expr    = IntegerExpression.Create(unit.Location);
            var literal = unit.Expect(LoreToken.IntLiteral).Value;

            // Try parsing the string
            ulong intval;

            try {
                intval = ulong.Parse(literal, NumberStyles.Integer);
            } catch (Exception e) {
                throw LoreException.Create(unit.Location).Describe($"Failed to parse integer literal: ${e.Message}");
            }

            // Determine the size of the integer
            expr.SetSize(IntegerSize.ULong);
            if (intval <= (byte)sbyte.MaxValue)
            {
                expr.SetSize(IntegerSize.SByte);
            }
            else if (intval <= byte.MaxValue)
            {
                expr.SetSize(IntegerSize.UByte);
            }
            else if (intval <= (ushort)short.MaxValue)
            {
                expr.SetSize(IntegerSize.SShort);
            }
            else if (intval <= ushort.MaxValue)
            {
                expr.SetSize(IntegerSize.UShort);
            }
            else if (intval <= int.MaxValue)
            {
                expr.SetSize(IntegerSize.SWord);
            }
            else if (intval <= uint.MaxValue)
            {
                expr.SetSize(IntegerSize.UWord);
            }
            else if (intval <= long.MaxValue)
            {
                expr.SetSize(IntegerSize.SLong);
            }

            // Set the value and return
            expr.SetValue(intval);
            return(expr);
        }
        void CompileAssignment(AssignStatement stmt, NamedParameter identifier, AstNode expr)
        {
            // Check if the variable already exists in the parent scope
            Symbol sym;

            if (Table.TopScope.FindSymbol(identifier.Name.Name, out sym))
            {
                // The variable already exists
                throw LoreException.Create(Location)
                      .Describe($"Redefinition of variable '{identifier.Name.Name}'.")
                      .Describe($"Previous definition was at '{sym.Location}'.");
            }

            // Compile the expression
            expr.Visit(this);

            // Get the expression value and type
            var exprVal     = Stack.Pop().Value;
            var exprValType = exprVal.TypeOf();

            // Check if the identifier has a type
            if (identifier.HasType)
            {
                var identType = Helper.GetBuiltinTypeFromString(identifier.Type.Name);

                // Check if the type of the identifier is different
                // from the type of the expression
                if (!Helper.CompareType(identType, exprValType))
                {
                    // Try casting the expression value to the expected type
                    exprVal = Helper.BuildCast(Builder, exprVal, identType);
                }

                // Set the type of the expression to the type of the identifier
                exprValType = identType;
            }

            // Allocate the variable
            var ptr = LLVM.BuildAlloca(Builder, exprValType, identifier.Name.Name);

            // Store the value in the variable
            LLVM.BuildStore(Builder, exprVal, ptr);

            // Add the variable to the symbol table
            var name = identifier.Name.Name;

            sym = Symbol.CreatePtr(name, ptr, Location, stmt.Mutable);
            Table.AddSymbol(sym);
        }
Esempio n. 8
0
        public LLVMTypeRef GetBuiltinTypeFromString(string type)
        {
            switch (type)
            {
            case "void":
                return(VoidType);

            case "bool":
                return(BoolType);

            case "char":
            case "int8":
                return(Int8Type);

            case "uint8":
                return(UInt8Type);

            case "int16":
                return(Int16Type);

            case "uint16":
                return(UInt16Type);

            case "int":
            case "int32":
                return(Int32Type);

            case "uint":
            case "uint32":
                return(UInt32Type);

            case "int64":
                return(Int64Type);

            case "uint64":
                return(UInt64Type);

            case "float":
                return(FloatType);

            case "double":
                return(DoubleType);

            case "string":
                return(StringType);
            }
            throw LoreException.Create(Visitor.Location).Describe($"Unable to resolve type: '{type}'");
        }
Esempio n. 9
0
        /// <summary>
        /// Expect the specified token and string.
        /// </summary>
        /// <param name="token">Token.</param>
        /// <param name="strval">Strval.</param>
        public Lexeme <LoreToken> Expect(LoreToken token, string strval)
        {
            var current = Current;

            if (Accept(token, strval))
            {
                return(current);
            }
            if (!See())
            {
                throw LoreException.Create(Location).Describe("Unexpected end of file.");
            }
            var next = Read();

            throw LoreException.Create(Location).Describe($"Unexpected token: '{next.Value}' ({next.Token})");
        }
Esempio n. 10
0
        void CompileName(NameExpression expr)
        {
            // Check if the variable exists
            Symbol sym;

            if (!Table.FindSymbol(expr.Name, out sym))
            {
                // The variable does not exist
                // Throw an exception
                throw LoreException.Create(Location).Describe($"Undefined variable: '{expr.Name}'");
            }

            // TODO: Check if the variable was captured

            // Push the variable
            Stack.Push(Symbol.CreateAnonymous(sym.Value));
        }
Esempio n. 11
0
        FloatExpression ParseFloat()
        {
            var expr    = FloatExpression.Create(unit.Location);
            var literal = unit.Expect(LoreToken.FloatLiteral).Value;

            // Try parsing the string
            double floatval;

            try {
                floatval = double.Parse(literal, NumberStyles.Float, NumberFormatInfo.InvariantInfo);
            } catch (Exception e) {
                throw LoreException.Create(unit.Location).Describe($"Failed to parse float literal: ${e.Message}");
            }

            // Set the value and return
            expr.SetValue(floatval);
            return(expr);
        }
Esempio n. 12
0
        /*
         *  => [captures...] expression
         * or
         *  => [captures...] { code... }
         * or
         *  (parameters...) => [captures...] expression
         * or
         *  (parameters...) => [captures...] { code... }
         */
        LambdaExpression ParseLambda(TupleExpression argumentList = null)
        {
            var lambda = LambdaExpression.Create(unit.Location);

            // Parse parameter list
            if (argumentList == null || argumentList.Count == 0)
            {
                if (unit.Match(LoreToken.OpenParen))
                {
                    var parameters = ParseDeclarationArgumentList();
                    lambda.SetParameters(parameters);
                }
            }
            else
            {
                var lst = new List <NamedParameter> ();
                foreach (var argument in argumentList.Items)
                {
                    var name = argument as NameExpression;
                    if (name == null)
                    {
                        throw LoreException.Create(unit.Location).Describe($"Invalid parameter list in lambda declaration.");
                    }
                    lst.Add(NamedParameter.Create(name));
                }
                lambda.SetParameters(lst);
            }

            // Expect arrow operator
            unit.Expect(LoreToken.Operator, "=>");

            // Create master code block
            CodeBlock master = CodeBlock.Create(unit.Location);

            // Parse captures
            if (unit.Match(LoreToken.OpenBracket))
            {
                // Parse captures
                unit.Expect(LoreToken.OpenBracket);
                while (!unit.Match(LoreToken.CloseBracket))
                {
                    var lex     = unit.Read();
                    var capture = Capture.Create(unit, lex);
                    master.AddCapture(capture);
                }
                unit.Expect(LoreToken.CloseBracket);
            }

            // Parse block
            if (unit.Match(LoreToken.OpenBrace))
            {
                var block = ParseBlockWithoutCaptures();

                // Merge captures
                master.Merge(block);
            }

            // Or parse expression
            else
            {
                // Create return statement for the result of the expression
                var retstmt = ReturnStatement.Create(unit.Location);
                retstmt.SetExpression(ParseExpression());

                // Create a new block with the return statement
                var block = CodeBlock.Create(unit.Location);
                block.AddChild(retstmt);

                // Merge captures
                master.Merge(block);
            }

            // Set the lambda body
            lambda.SetBody(master);
            Console.WriteLine(lambda);
            return(lambda);
        }
Esempio n. 13
0
        void CompileFunction(FunctionDeclaration funcdecl)
        {
            // Check if a symbol with the name of the function is already defined
            Symbol sym = null;

            // Check if only local functions should be generated
            if (Table.TopScope.IsFunction)
            {
                // Declare the function
                DeclareFunctionPrototype(funcdecl);
            }

            if (!Table.FindSymbol(funcdecl.Name, out sym))
            {
                throw LoreException.Create(funcdecl.Location).Describe($"Undefined function: '{funcdecl.Name}'.");
            }

            // Check if the symbol is a prototype
            if (!sym.IsPrototype)
            {
                throw new LoreException(funcdecl.Location).Describe($"Function without prototype: '{funcdecl.Name}'.");
            }

            // Get the function prototype
            LLVMValueRef functionRef = sym.Value;

            // Enter a new scope for the function
            Table.PushScope(Scope.CreateFunction(functionRef));

            // Check if the function returns multiple values
            var returnType       = LLVM.VoidType();
            var tupleReturnTypes = new LLVMTypeRef [0];

            if (funcdecl.ReturnsTuple)
            {
                var count = funcdecl.TupleReturnTypes.Count;
                tupleReturnTypes = new LLVMTypeRef [count];
                for (var i = 0; i < count; i++)
                {
                    var current = funcdecl.TupleReturnTypes [i];
                    tupleReturnTypes [i] = Helper.GetBuiltinTypeFromString(current.Name);
                }
                returnType = LLVM.StructType(tupleReturnTypes, true);
            }

            // Create the return type
            else if (funcdecl.HasReturnType)
            {
                returnType = Helper.GetBuiltinTypeFromString(funcdecl.ReturnType.Name);
            }

            // Add function parameters
            for (var i = 0; i < funcdecl.Parameters.Count; i++)
            {
                var argname = funcdecl.Parameters [i].Name.Name;

                // Get the i-th function parameter
                var param = LLVM.GetParam(functionRef, (uint)i);

                // Set the correct name
                LLVM.SetValueName(param, argname);

                // Add the named parameter to the scope
                Table.AddSymbol(Symbol.Create(argname, param, Location));
            }

            // Create the entry block for the function
            var block = LLVM.AppendBasicBlock(functionRef, "entry");

            LLVM.PositionBuilderAtEnd(Builder, block);

            // Visit the function body
            funcdecl.VisitChildren(this);

            // Return void and clear the stack if the
            // function return type is void
            if (Helper.CompareType(returnType, LLVM.VoidType()))
            {
                // Build return statement
                LLVM.BuildRetVoid(Builder);
            }
            else if (Stack.Count == 0)
            {
                // The function has a return type,
                // but nothing was returned!
                if (funcdecl.HasReturnType)
                {
                    throw LoreException.Create(Location)
                          .Describe($"Function '{funcdecl.Name}' has return type '{funcdecl.ReturnType.Name}' but does not return anything!")
                          .Resolve($"Return a value of type '{funcdecl.ReturnType.Name}' or change the return type to 'void'.");
                }

                // There are no elements on the stack
                // Just return void
                LLVM.BuildRetVoid(Builder);
            }
            else if (funcdecl.ReturnsTuple && Stack.Count >= funcdecl.TupleReturnTypes.Count)
            {
                // Prepare element array
                var elems = new LLVMValueRef [funcdecl.TupleReturnTypes.Count];

                // Fill the element array
                for (var i = 0; i < elems.Length; i++)
                {
                    // Pop the element from the stack
                    var current = Stack.Pop().Value;

                    // Check if the current element is a defined symbol
                    if (Table.FindSymbolByRef(current, out sym))
                    {
                        // Check if the current element is a pointer
                        if (sym.IsPointer)
                        {
                            // Load the element
                            current = LLVM.BuildLoad(Builder, current, "tmpload");
                        }
                    }

                    // Cast the element to the right type
                    current = Helper.BuildCast(Builder, current, tupleReturnTypes [i]);

                    // Add the element to the array
                    elems [elems.Length - i - 1] = current;
                }

                // Build the return statement
                LLVM.BuildAggregateRet(Builder, elems);
                // What the hellt
            }
            else if (funcdecl.HasReturnType && Stack.Count > 0)
            {
                // There are elements on the stack
                // Take the top element from the stack
                var elem = Stack.Pop().Value;

                // Check if the return element is a defined symbol
                if (Table.FindSymbolByRef(elem, out sym))
                {
                    // Check if the return element is a pointer
                    if (sym.IsPointer)
                    {
                        // Load the element
                        elem = LLVM.BuildLoad(Builder, elem, "tmpload");
                    }
                }

                Helper.BuildOptimalReturn(Builder, elem, returnType);
            }
            else
            {
                throw LoreException.Create(Location)
                      .Describe($"Unable to construct a return value for function '{funcdecl.Name}'.")
                      .Describe($"This is a compiler bug.");
            }

            // Validate the function
            if (LLVM.VerifyFunction(functionRef, LLVMVerifierFailureAction.LLVMPrintMessageAction).Value != 0)
            {
                throw LoreException.Create(funcdecl.Location).Describe($"Function failed to compile: '{funcdecl.Name}'");
            }

            // Exit the scope of the function
            Table.PopScope();

            if (Table.TopScope.IsFunction)
            {
                var func = Table.TopScope.Function;
                LLVM.PositionBuilderAtEnd(Builder, func.GetEntryBasicBlock());
            }

            // Add the function symbol
            Table.AddSymbol(Symbol.Create(funcdecl.Name, functionRef, funcdecl.Location));
            Stack.Clear();
        }
Esempio n. 14
0
        internal void DeclareFunctionPrototype(FunctionDeclaration funcdecl)
        {
            // Prepare argument type array
            var argumentCount = funcdecl.Parameters.Count;
            var arguments     = new LLVMTypeRef [Math.Max(argumentCount, 0)];

            // Check if the function is already defined
            Symbol sym;

            if ((Table.TopScope.IsFunction && Table.TopScope.FindSymbol(funcdecl.Name, out sym)) ||
                (!Table.TopScope.IsFunction && Table.FindSymbol(funcdecl.Name, out sym)))
            {
                var e = LoreException.Create(funcdecl.Location).Describe($"Redefinition of function '{funcdecl.Name}'!");
                e.Describe($"Previous declaration was at {sym.Location}.");
                e.Resolve($"Rename the function to avoid a collision.");
                throw e;
            }

            // Add function parameter types to array
            for (var i = 0; i < funcdecl.Parameters.Count; i++)
            {
                arguments [i] = Helper.GetBuiltinTypeFromString(funcdecl.Parameters [i].Type.Name);
            }

            // Check if the function returns multiple values
            var returnType       = LLVM.VoidType();
            var tupleReturnTypes = new LLVMTypeRef [0];

            if (funcdecl.ReturnsTuple)
            {
                var count = funcdecl.TupleReturnTypes.Count;
                tupleReturnTypes = new LLVMTypeRef [count];
                for (var i = 0; i < count; i++)
                {
                    var current = funcdecl.TupleReturnTypes [i];
                    tupleReturnTypes [i] = Helper.GetBuiltinTypeFromString(current.Name);
                }
                returnType = LLVM.StructType(tupleReturnTypes, true);
            }

            // Create the return type
            else if (funcdecl.HasReturnType)
            {
                returnType = Helper.GetBuiltinTypeFromString(funcdecl.ReturnType.Name);
            }

            // Create the function type
            var functionType = LLVM.FunctionType(
                ReturnType: returnType,
                ParamTypes: arguments,
                IsVarArg: LLVMFalse
                );

            // Create the actual function
            var functionRef = LLVM.AddFunction(LLVMModule, funcdecl.Name, functionType);

            LLVM.SetLinkage(functionRef, LLVMLinkage.LLVMExternalLinkage);

            // Add the function prototype as a symbol
            Table.AddSymbol(Symbol.CreatePrototype(funcdecl.Name, functionRef, funcdecl.Location));
        }
Esempio n. 15
0
        public LLVMValueRef BuildCast(LLVMBuilderRef builder, LLVMValueRef elem, LLVMTypeRef targetType)
        {
            // Check if the type of the element equals the targe type
            if (CompareType(elem, targetType))
            {
                // There is no need to cast
                // Just return the element
                return(elem);
            }

            // Strings need special handling
            if (CompareType(targetType, StringType))
            {
                LLVMValueRef indices;
                var          gep = LLVM.BuildGEP(builder, elem, out indices, 0u, "tmpgep");
                var          ptr = LLVM.BuildPointerCast(builder, gep, StringType, "tmpptrcast");
                return(ptr);
            }

            string strtype1, strtype2;

            switch (targetType.TypeKind)
            {
            case LLVMTypeKind.LLVMIntegerTypeKind:

                // Check if the integer fits
                if (IsInteger(elem))
                {
                    var lwidth = elem.TypeOf().GetIntTypeWidth();
                    var rwidth = targetType.GetIntTypeWidth();
                    if (lwidth > rwidth)
                    {
                        // The width of the result type is higher
                        // than the width of the element type
                        // Throw an exception
                        strtype1 = elem.TypeOf().PrintTypeToString();
                        strtype2 = targetType.PrintTypeToString();
                        throw LoreException.Create(Visitor.Location)
                              .Describe($"Unable to cast element of type '{strtype1}' to '{strtype2}':")
                              .Describe($"The element is too big for the target integer type.");
                    }
                }

                // Perform a float to signed integer cast if needed
                else if (IsFloatOrDouble(elem))
                {
                    elem = LLVM.BuildFPToSI(builder, elem, targetType, "tmpfptosicast");
                }

                // Unsupported element type
                else
                {
                    // Unable to perform a meaningful cast
                    strtype1 = elem.TypeOf().PrintTypeToString();
                    strtype2 = targetType.PrintTypeToString();
                    throw LoreException.Create(Visitor.Location).Describe($"Unable to cast element of type '{strtype1}' to '{strtype2}':");
                }

                // Perform an integer cast
                return(LLVM.BuildIntCast(builder, elem, targetType, "tmpcast"));

            case LLVMTypeKind.LLVMFloatTypeKind:
            case LLVMTypeKind.LLVMDoubleTypeKind:

                // Perform a signed integer to float cast if needed
                if (IsInteger(elem))
                {
                    elem = LLVM.BuildSIToFP(builder, elem, targetType, "tmpsitofpcast");
                }
                return(LLVM.BuildFPCast(builder, elem, targetType, "tmpfcast"));
            }

            // Unable to perform a meaningful cast
            strtype1 = elem.TypeOf().PrintTypeToString();
            strtype2 = targetType.PrintTypeToString();
            throw LoreException.Create(Visitor.Location).Describe($"Unable to cast element of type '{strtype1}' to '{strtype2}':");
        }
Esempio n. 16
0
        void CompileBinaryOperation(BinaryExpression expr)
        {
            // Compile the expression
            expr.VisitChildren(this);

            // Pop the right value from the stack
            var          right  = Stack.Pop().Value;
            var          left   = Stack.Pop().Value;
            LLVMValueRef result = LLVMNull;

            Func <LoreException> BuildUnsupportedBinaryOperationException = () => {
                var l = left.TypeOf().PrintTypeToString().Trim();
                var r = right.TypeOf().PrintTypeToString().Trim();
                return(LoreException.Create(Location)
                       .Describe($"Invalid binary operation: {expr.Operation}")
                       .Describe($"The operation is unsupported on types '{l}' and '{r}'"));
            };

            if (expr.Operation == BinaryOperation.Assign)
            {
                // Try to find the symbol
                Symbol sym;
                if (!Table.FindSymbolByRef(left, out sym))
                {
                    // There is nothing to process
                    throw BuildUnsupportedBinaryOperationException();
                }

                // Check if the variable is mutable
                if (!sym.IsMutable)
                {
                    // The variable is immutable
                    throw BuildUnsupportedBinaryOperationException();
                }

                // Check if the symbol is a pointer
                if (!sym.IsPointer)
                {
                    // It is not possible to assign a new value to
                    // the specified variable, since it is not a pointer
                    // and is therefore not allocated on the stack.
                    // Throw an exception
                    throw LoreException.Create(Location).Describe($"Attempt to modify constant: '{sym.Name}");
                }

                // Assign the new value to the variable
                var targetType = left.TypeOf().GetElementType();
                right = Helper.BuildCast(Builder, right, targetType);
                LLVM.BuildStore(Builder, right, left);

                // Set the result
                result = right;
            }

            else if (Helper.IsInteger(left) && Helper.IsInteger(right))
            {
                switch (expr.Operation)
                {
                case BinaryOperation.Add:
                    result = LLVM.BuildAdd(Builder, left, right, "tmpadd");
                    break;

                case BinaryOperation.Subtract:
                    result = LLVM.BuildSub(Builder, left, right, "tmpsub");
                    break;

                case BinaryOperation.Divide:
                    result = LLVM.BuildUDiv(Builder, left, right, "tmpdiv");
                    break;

                case BinaryOperation.Multiply:
                    result = LLVM.BuildMul(Builder, left, right, "tmpmul");
                    break;

                default:
                    throw BuildUnsupportedBinaryOperationException();
                }
            }
            else if ((Helper.IsFloatOrDouble(left) && Helper.IsInteger(right)) ||
                     (Helper.IsFloatOrDouble(right) && Helper.IsInteger(left)) ||
                     (Helper.IsFloatOrDouble(left) && Helper.IsFloatOrDouble(right)))
            {
                switch (expr.Operation)
                {
                case BinaryOperation.Add:
                    result = LLVM.BuildFAdd(Builder, left, right, "tmpfadd");
                    break;

                case BinaryOperation.Subtract:
                    result = LLVM.BuildFSub(Builder, left, right, "tmpfsub");
                    break;

                case BinaryOperation.Divide:
                    result = LLVM.BuildFDiv(Builder, left, right, "tmpfdiv");
                    break;

                case BinaryOperation.Multiply:
                    result = LLVM.BuildFMul(Builder, left, right, "tmpfmul");
                    break;

                default:
                    throw BuildUnsupportedBinaryOperationException();
                }
            }
            else
            {
                throw BuildUnsupportedBinaryOperationException();
            }

            Stack.Push(Symbol.CreateAnonymous(result));
        }
Esempio n. 17
0
        void CompileUnaryOperation(UnaryExpression expr)
        {
            // Compile the expression
            expr.VisitChildren(this);

            // Pop the right value from the stack
            var          right  = Stack.Pop().Value;
            LLVMValueRef result = LLVMNull;

            Func <LoreException> BuildUnsupportedUnaryOperationException = () => {
                var r = right.TypeOf().PrintTypeToString();
                return(LoreException.Create(Location)
                       .Describe($"Invalid unary operation: {expr.Operation}")
                       .Describe($"The operation is unsupported on type '{r}'"));
            };

            if (Helper.IsBoolean(right))
            {
                if (expr.Operation == UnaryOperation.LogicalNot)
                {
                }
                else
                {
                    throw BuildUnsupportedUnaryOperationException();
                }
            }
            else if (Helper.IsFloatOrDouble(right))
            {
                switch (expr.Operation)
                {
                case UnaryOperation.Negate:
                    result = LLVM.BuildFNeg(Builder, right, "unop");
                    break;

                default:
                    throw BuildUnsupportedUnaryOperationException();
                }
            }
            else if (Helper.IsInteger(right))
            {
                switch (expr.Operation)
                {
                case UnaryOperation.Negate:
                    result = LLVM.BuildNeg(Builder, right, "unop");
                    break;

                case UnaryOperation.BitwiseNot:
                    result = LLVM.BuildNot(Builder, right, "unop");
                    break;

                default:
                    throw BuildUnsupportedUnaryOperationException();
                }
            }
            else
            {
                throw BuildUnsupportedUnaryOperationException();
            }

            Stack.Push(Symbol.CreateAnonymous(result));
        }
Esempio n. 18
0
        AstNode ParseTerm()
        {
            // Try parsing a name
            if (unit.Match(LoreToken.Identifier))
            {
                return(ParseName());
            }

            // Try parsing an integer
            if (unit.Match(LoreToken.IntLiteral))
            {
                return(ParseInteger());
            }

            // Try parsing a float
            if (unit.Match(LoreToken.FloatLiteral))
            {
                return(ParseFloat());
            }

            // Try parsing a list
            if (unit.Match(LoreToken.OpenBracket))
            {
                return(ParseList());
            }

            // Try parsing a tuple, a lambda or an expression
            if (unit.Match(LoreToken.OpenParen))
            {
                unit.Skip();
                var istuple = false;

                // Parse the first expression
                var expr = ParseExpression();

                // Create a temporary tuple expression
                // that holds the arguments of the lambda expression
                TupleExpression tmp = TupleExpression.Create(unit.Location);
                tmp.Add(expr);

                // Try parsing a tuple
                TupleExpression tpl = null;
                if (unit.Accept(LoreToken.Comma))
                {
                    tpl     = ParseTuple(expr);
                    istuple = true;
                }

                // Read the remaning parenthesis if
                // we did not successfully parse a tuple
                else
                {
                    unit.Expect(LoreToken.CloseParen);
                }

                // Get the correct tuple
                tpl = tpl ?? tmp;

                // Try parsing a lambda expression
                if (unit.Match(LoreToken.Operator, "=>"))
                {
                    return(ParseLambda(tpl));
                }

                // Return the tuple if needed
                if (istuple)
                {
                    return(tpl);
                }

                // This is neither a tuple nor a lambda
                // Just return the expression
                return(expr);
            }

            // Try parsing a keyword
            if (unit.Match(LoreToken.Keyword))
            {
                // TODO: Implement true, false, null, etc
                switch (unit.Current.Value)
                {
                case "true":
                    unit.Skip();
                    // TODO: Return TrueExpression
                    return(null);

                case "false":
                    unit.Skip();
                    // TODO: Return FalseExpression
                    return(null);

                case "null":
                    unit.Skip();
                    // TODO: Return NullExpression
                    return(null);
                }
            }

            // Try parsing a string
            if (unit.Match(LoreToken.StringLiteral))
            {
                return(ParseString());
            }

            throw LoreException.Create(unit.Location).Describe("Unexpected end of term.");
        }