private void CheckTypeForSpecialization(AST.Type type) { type = type.Desugar(); ClassTemplateSpecialization specialization; type = type.GetFinalPointee() ?? type; if (!type.TryGetDeclaration(out specialization)) return; if (specialization.Ignore || specialization.TemplatedDecl.TemplatedClass.Ignore || specialization.IsIncomplete || specialization.TemplatedDecl.TemplatedClass.IsIncomplete || specialization is ClassTemplatePartialSpecialization || specialization.Arguments.Any(a => UnsupportedTemplateArgument(specialization, a))) return; TypeMap typeMap; if (Context.TypeMaps.FindTypeMap(specialization, out typeMap)) { var mappedTo = typeMap.CSharpSignatureType(new CSharpTypePrinterContext { Type = type }); mappedTo = mappedTo.Desugar(); mappedTo = (mappedTo.GetFinalPointee() ?? mappedTo); if (mappedTo.IsPrimitiveType() || mappedTo.IsPointerToPrimitiveType() || mappedTo.IsEnum()) return; } HashSet<ClassTemplateSpecialization> list; if (specializations.ContainsKey(specialization.TranslationUnit.Module)) list = specializations[specialization.TranslationUnit.Module]; else specializations[specialization.TranslationUnit.Module] = list = new HashSet<ClassTemplateSpecialization>(); list.Add(specialization); }
private List <Parameter> RemoveOperatorParams(Function function) { var functionParams = new List <Parameter>(function.Parameters); if (!function.IsOperator || (Context.Options.GeneratorKind != GeneratorKind.CLI && Context.Options.GeneratorKind != GeneratorKind.CSharp)) { return(functionParams); } // C++ operators in a class have no class param unlike C# // but we need to be able to compare them to free operators. Parameter param = functionParams.Find(p => p.Kind == ParameterKind.Regular); if (param != null) { AST.Type type = param.Type.Desugar(); type = (type.GetFinalPointee() ?? type).Desugar(); Class @class; if (type.TryGetClass(out @class) && function.Namespace == @class) { functionParams.Remove(param); } } return(functionParams); }
/// <remarks> /// Checks if a given type is invalid, which can happen for a number of /// reasons: incomplete definitions, being explicitly ignored, or also /// by being a type we do not know how to handle. /// </remarks> bool HasInvalidType(AST.Type type, out string msg) { if (type == null) { msg = "null"; return(true); } if (!IsTypeComplete(type)) { msg = "incomplete"; return(true); } if (IsTypeIgnored(type)) { msg = "ignored"; return(true); } var arrayType = type as ArrayType; PrimitiveType primitive; if (arrayType != null && arrayType.SizeType == ArrayType.ArraySize.Constant && !arrayType.Type.IsPrimitiveType(out primitive) && !arrayType.Type.Desugar().IsPointerToPrimitiveType()) { msg = "unsupported"; return(true); } msg = null; return(false); }
bool IsTypeIgnored(AST.Type type) { var checker = new TypeIgnoreChecker(Driver.TypeDatabase); type.Visit(checker); return(checker.IsIgnored); }
private bool CheckDefaultParametersForAmbiguity(Function function, Function overload) { List <Parameter> functionParams = RemoveOperatorParams(function); List <Parameter> overloadParams = RemoveOperatorParams(overload); var commonParameters = Math.Min(functionParams.Count, overloadParams.Count); var i = 0; for (; i < commonParameters; ++i) { AST.Type funcType = functionParams[i].Type.GetMappedType( TypeMaps, Options.GeneratorKind); AST.Type overloadType = overloadParams[i].Type.GetMappedType( TypeMaps, Options.GeneratorKind); AST.Type funcPointee = funcType.GetFinalPointee() ?? funcType; AST.Type overloadPointee = overloadType.GetFinalPointee() ?? overloadType; if (((funcPointee.IsPrimitiveType() || overloadPointee.IsPrimitiveType()) && !funcType.Equals(overloadType)) || !funcPointee.Equals(overloadPointee)) { return(false); } } for (; i < functionParams.Count; ++i) { var funcParam = functionParams[i]; if (!funcParam.HasDefaultValue) { return(false); } } for (; i < overloadParams.Count; ++i) { var overloadParam = overloadParams[i]; if (!overloadParam.HasDefaultValue) { return(false); } } if (functionParams.Count > overloadParams.Count) { overload.ExplicitlyIgnore(); } else { function.ExplicitlyIgnore(); } return(true); }
public Declaration(Position position, string name, SymbolKind kind, AST.Type type) : base(position) { _name = name; _kind = kind; _type = type; _type.Parent = this; }
public void AddField(string name, AST.Type type) { if (!Fields.ContainsKey(name)) { Fields.Add(name, type); } else { throw new Exception("Sorry, but there is another field with the same name :("); } }
public void AddMethod(string name, AST.Type returnType) { if (!Methods.ContainsKey(name)) { Methods.Add(name, new Method(returnType)); } else { throw new Exception("Method already exists!"); } }
public void AddVariable(string name, AST.Type type) { if (!Variables.ContainsKey(name)) { Variables.Add(name, type); } else { throw new Exception("Variable name and stuff and there is one..."); } }
public void AddParam(string name, AST.Type type) { if (!Parameters.ContainsKey(name)) { Parameters.Add(name, type); } else { throw new Exception("Parameter name exists already..."); } }
private void CheckForInternalSpecialization(Declaration container, AST.Type type) { ASTUtils.CheckTypeForSpecialization(type, container, specialization => { if (!specializations.Contains(specialization)) { internalSpecializations.Add(specialization); CheckLayoutFields(specialization); } }, Context.TypeMaps, true); }
private Ast Declaration() { if (!IsType(_tokenStream.Current)) { return(null); } AST.Type type = new AST.Type(_tokenStream.Consume()); IdentifierToken ident = _tokenStream.Take <IdentifierToken>(); return(new VariableDeclaration(ident, type)); }
private bool CheckDefaultParametersForAmbiguity(Function function, Function overload) { var commonParameters = Math.Min(function.Parameters.Count, overload.Parameters.Count); var i = 0; for (; i < commonParameters; ++i) { AST.Type funcType = GetFinalType(function.Parameters[i]); AST.Type overloadType = GetFinalType(overload.Parameters[i]); AST.Type funcPointee = funcType.GetFinalPointee() ?? funcType; AST.Type overloadPointee = overloadType.GetFinalPointee() ?? overloadType; if (((funcPointee.IsPrimitiveType() || overloadPointee.IsPrimitiveType()) && !funcType.Equals(overloadType)) || !funcPointee.Equals(overloadPointee)) { return(false); } } for (; i < function.Parameters.Count; ++i) { var funcParam = function.Parameters[i]; if (!funcParam.HasDefaultValue) { return(false); } } for (; i < overload.Parameters.Count; ++i) { var overloadParam = overload.Parameters[i]; if (!overloadParam.HasDefaultValue) { return(false); } } if (function.Parameters.Count > overload.Parameters.Count) { overload.ExplicitlyIgnore(); } else { function.ExplicitlyIgnore(); } return(true); }
private void CheckForInternalSpecialization(Declaration container, AST.Type type) { ASTUtils.CheckTypeForSpecialization(type, container, s => { if (!specializations.Contains(s)) { internalSpecializations.Add(s); foreach (var f in s.Fields) { f.Visit(this); } } }, Context.TypeMaps, true); }
public FunctionDeclaration(Position position, string name, AST.Type type, ParameterDeclaration[] parameters, Expression body) : base(position, name, SymbolKind.Function, type) { _parameters = parameters; foreach (ParameterDeclaration parameter in _parameters) { parameter.Parent = this; } // body MAY be null for predefined functions _body = body; if (_body != null) { _body.Parent = this; } }
public bool CompareTypes(AST.Type t1, AST.Type t2) { if (t1.GetType() != t2.GetType()) { return(false); } if (t1 is ObjectType to1 && t2 is ObjectType to2) { if (to1.Name != to2.Name) { return(false); } } return(true); }
public void AddMethodVariable(string className, string methodName, string varName, AST.Type type) { program.classTables[className].Methods[methodName].AddVariable(varName, type); }
public VariableDeclaration(Position position, string name, AST.Type type) : base(position, name, SymbolKind.Variable, type) { }
static bool IsTypeComplete(AST.Type type) { var checker = new TypeCompletionChecker(); return(type.Visit(checker)); }
public abstract void Visit(AST.Type visitable);
public override void Visit(AST.Type visitable) { WriteIndentantion(true).AppendLine($"Type: {visitable.Token.Value}"); _indentLevel--; }
public ParameterDeclaration(Position position, string name, AST.Type type) : base(position, name, SymbolKind.Parameter, type) { }
public ConstantDeclaration(Position position, string name, AST.Type type, Expression expression) : base(position, name, SymbolKind.Constant, type) { _expression = expression; _expression.Parent = this; }
public void AddField(string className, string fieldName, AST.Type type) { program.classTables[className].AddField(fieldName, type); }
public LiteralNode(object value, AST.Type type) { Value = value; Type = type; }
public TypeRefNode(AST.Type type, bool?abi = null) { Type = type; Abi = abi; }
public void AddMethod(string className, string methodName, AST.Type returnType) { program.classTables[className].AddMethod(methodName, returnType); }
public bool TypeChecking(Node tree, string currentClass, string currentMethod) { switch (tree) { case MethodBody methodBody: { foreach (var stm in methodBody.Statements) { TypeChecking(stm, currentClass, currentMethod); } if (symbolTable.GetMethodReturnType(currentClass, currentMethod).GetType() != TypeOf(methodBody.ReturnExpression, currentClass, currentMethod).GetType()) { throw new Exception("Wrong return type"); } else { return(true); } } case BlockStatement blockStm: { bool result = false; foreach (var stm in blockStm.Statements) { result = TypeChecking(stm, currentClass, currentMethod); } return(result); } case IfElseBlock ifElse: { if (!(TypeOf(ifElse.Expression, currentClass, currentMethod) is AST.Boolean)) { throw new Exception("Sorry but an if statement awaits a boolean :("); } else { bool a = TypeChecking(ifElse.FalseBranch, currentClass, currentMethod); bool b = TypeChecking(ifElse.TrueBranch, currentClass, currentMethod); return(a && b); } } case WhileBlock whileBlock: { if (!(TypeOf(whileBlock.Expression, currentClass, currentMethod) is AST.Boolean)) { throw new Exception("While type stupid"); } else { return(TypeChecking(whileBlock.Statement, currentClass, currentMethod)); } } case VarAssignment varAss: { AST.Type varType = symbolTable.GetVarType(currentClass, currentMethod, varAss.Id); if (varType.GetType() != TypeOf(varAss.Expression, currentClass, currentMethod).GetType()) { throw new Exception("Variable Assignment type is shit"); } else { return(true); } } case ArrayAssignment arrAss: { if (!(TypeOf(arrAss.Index, currentClass, currentMethod) is Int) || !(TypeOf(arrAss.Value, currentClass, currentMethod) is Int)) { throw new Exception("???"); } else { return(true); } } case Print print: { if (TypeOf(print.Expression, currentClass, currentMethod) is AST.Int) { return(true); } else { return(false); } } case Write write: { if (TypeOf(write.Expression, currentClass, currentMethod) is AST.IntegerLit) { return(true); } else { //throw new Exception("Write is shit"); return(true); } } default: throw new Exception("No thingy matched"); } }
public AST.Type TypeOf(Expression exp, string currentClass, string currentMethod) { switch (exp) { case Identifier id: { return(symbolTable.GetVarType(currentClass, currentMethod, id.Name)); } case And and: { AST.Type left = TypeOf(and.Left, currentClass, currentMethod); AST.Type right = TypeOf(and.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new AST.Boolean()); } } case Plus plus: { AST.Type left = TypeOf(plus.Left, currentClass, currentMethod); AST.Type right = TypeOf(plus.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case Minus minus: { AST.Type left = TypeOf(minus.Left, currentClass, currentMethod); AST.Type right = TypeOf(minus.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case Times times: { AST.Type left = TypeOf(times.Left, currentClass, currentMethod); AST.Type right = TypeOf(times.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case Division division: { AST.Type left = TypeOf(division.Left, currentClass, currentMethod); AST.Type right = TypeOf(division.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new Int()); } } case LessThan lt: { AST.Type left = TypeOf(lt.Left, currentClass, currentMethod); AST.Type right = TypeOf(lt.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new AST.Boolean()); } } case GreaterThan gt: { AST.Type left = TypeOf(gt.Left, currentClass, currentMethod); AST.Type right = TypeOf(gt.Right, currentClass, currentMethod); if (left.GetType() != right.GetType()) { throw new Exception("Binary operator type fail and shit"); } else { return(new AST.Boolean()); } } case ArrayAccess arrAcc: { return(TypeOf(arrAcc.Val, currentClass, currentMethod)); } case ArrayLength arrlength: { if (!(TypeOf(arrlength.Exp, currentClass, currentMethod) is IntArray)) { throw new Exception(arrlength.Exp + " is not an array"); } else { return(new Int()); } } case MethodCall methodCall: { ObjectType expType; if (TypeOf(methodCall.Exp, currentClass, currentMethod) is ObjectType ot) { expType = ot; } else { throw new Exception("This method does not exist... Sorry bro"); } if (!symbolTable.ExistsMethod(expType.Name, methodCall.MethodName)) { throw new Exception("Method does not exist"); } AST.Type[] paramTypes = symbolTable.GetMethodParam(expType.Name, methodCall.MethodName); int i = 0; if (methodCall.Parameters == null) { return(symbolTable.GetMethodReturnType(expType.Name, methodCall.MethodName)); } foreach (var par in methodCall.Parameters) { if (!CompareTypes(TypeOf(par, currentClass, currentMethod), paramTypes[i])) { throw new Exception("Parameters type error"); } i++; } methodCall.EnhancedName = expType.Name + "$" + methodCall.MethodName; return(symbolTable.GetMethodReturnType(expType.Name, methodCall.MethodName)); } case Read read: { return(new AST.Boolean()); } case BooleanLit booleanLit: { return(new AST.Boolean()); } case IntegerLit intLit: { return(new Int()); } case This th: { return(new ObjectType(currentClass)); // TODO } case ArrayInstantiation arrInst: { TypeOf(arrInst.Length, currentClass, currentMethod); return(new AST.IntArray()); } case ObjectInstantiation objInst: { return(new ObjectType(objInst.ObjectId)); } case Not not: { TypeOf(not.Exp, currentClass, currentMethod); return(new AST.Boolean()); } case Parent par: { return(TypeOf(par.Exp, currentClass, currentMethod)); } } return(null); }
public void AddMethodParameter(string className, string methodName, string parameterName, AST.Type type) { program.classTables[className].Methods[methodName].AddParam(parameterName, type); }