Example #1
0
        private Node parseCall()
        {
            Node left = parsePrimary();

            while (true)
            {
                if (match(TType.OPEN_PAREN))
                {
                    if (!(left is Variable))
                    {
                        throw new Exception($"Invalid call target '{left.GetType().Name}', can only be a function.");
                    }

                    List <Node> args = new List <Node>();

                    if (!check(TType.CLOSE_PAREN))
                    {
                        do
                        {
                            args.Add(parseExpression());
                        } while (match(TType.COMMA));
                    }

                    consume(TType.CLOSE_PAREN, "Expected ')' after function call parameters");

                    left = new CallFunc(((Variable)left).Name.lexeme, args.ToArray());
                }
                else if (match(TType.OPEN_SQR))
                {
                    Node idx = parsePrimary();

                    if (!(left is Variable))
                    {
                        throw new Exception($"Expected variable name before indexing, got {idx.GetType().Name}");
                    }

                    consume(TType.CLOSE_SQR, "Expected ']' after index");
                    left = new IndexArray(left, idx);
                }
                else
                {
                    break;
                }
            }

            return(left);
        }
        private Type GetResultType(Node n)
        {
            if (n is IntLiteral)
            {
                return(ToType("int"));
            }

            else if (n is FloatLiteral)
            {
                return(ToType("float"));
            }

            else if (n is StringLiteral)
            {
                return(ToType("string"));
            }

            else if (n is BinaryOperation binop)
            {
                Type left  = GetResultType(binop.left);
                Type right = GetResultType(binop.right);

                if (IsNumericType(left) && !IsNumericType(right))
                {
                    throw new Exception($"Cannot perform '{binop.op.lexeme}' operation on '{left.Name}' and '{right.Name}'");
                }

                return(left);
            }
            else if (n is CastValue cast)
            {
                return(ToType(cast.type));
            }
            else if (n is ValToString)
            {
                return(ToType("string"));
            }

            else if (n is Variable var)
            {
                if (localSymbols.ContainsKey(var.Name.lexeme))
                {
                    return(localSymbols[var.Name.lexeme].LocalType);
                }
                else if (current_method_args.Contains(var.Name.lexeme))
                {
                    return(current_method_types[Array.IndexOf(current_method_args, var.Name.lexeme)]);
                }
                else if (globalSymbols.ContainsKey(var.Name.lexeme))
                {
                    return(globalSymbols[var.Name.lexeme].FieldType);
                }
                else
                {
                    throw new Exception($"Tried getting type of a undeclared variable '{var.Name.lexeme}'");
                }
            }

            else if (n is CallFunc cf)
            {
                if (externMethods.ContainsKey(cf.funcName))
                {
                    return(externMethods[cf.funcName].ReturnType);
                }

                else if (globalSymbols.ContainsKey(cf.funcName) && !(cTypeBuilder.GetMethod(cf.funcName) is null))
                {
                    MethodInfo method = cTypeBuilder.GetMethod(cf.funcName);
                    return(method.ReturnType);
                }
                else
                {
                    throw new Exception($"Unknown function '{cf.funcName}'");
                }
            }
            else if (n is IndexArray idxarr)
            {
                return(GetResultType(idxarr.value).GetElementType());
            }
            else if (n is CreateArray crarr)
            {
                return(ToType(crarr.arrayType));
            }
            else if (n is NewInstance newinst)
            {
                return(newinst.instanceType.type);
            }

            throw new Exception($"Cannot get result type of {n.GetType().FullName}");
        }