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}"); }