public override NodeFinderResult VisitDotExpr(AstDotExpr dot, int i = 0) { if (GetRelativeLocation(dot.Left.Location, i) == RelativeLocation.Same) { return(dot.Left.Accept(this, i)); } return(new NodeFinderResult(dot.Scope, expr: dot)); }
private AstUsingStmt AnalyseUseStatement(AstUsingStmt use) { use.Value.SetFlag(ExprFlags.ValueRequired, true); use.Value.AttachTo(use); use.Value = InferType(use.Value, null); if (use.Value.Type.IsErrorType) { return(use); } switch (use.Value.Type) { case CheezTypeType type: HandleUseType(use); break; case StructType str: { var tempVar = use.Value; //if (!tempVar.GetFlag(ExprFlags.IsLValue)) { tempVar = new AstTempVarExpr(use.Value, use.Value.GetFlag(ExprFlags.IsLValue)); tempVar.Replace(use.Value); tempVar.SetFlag(ExprFlags.IsLValue, true); tempVar = InferType(tempVar, use.Value.Type); use.Value = tempVar; } ComputeStructMembers(str.Declaration); foreach (var mem in str.Declaration.Members) { AstExpression expr = new AstDotExpr(tempVar, new AstIdExpr(mem.Name, false, use.Location), use.Location); //expr = InferType(expr, null); use.Scope.DefineUse(mem.Name, expr, true, out var u); } } break; default: ReportError(use, $"Can't use value of type '{use.Value.Type}'"); break; } return(use); }
public virtual ReturnType VisitDotExpr(AstDotExpr expr, DataType data = default) => default;
private void AnalyseFunction(AstFuncExpr func) { if (func.IsAnalysed) { return; } func.IsAnalysed = true; Log($"Analysing function {func.Name}", $"impl = {func.ImplBlock?.Accept(new SignatureAstPrinter())}", $"poly = {func.IsGeneric}"); PushLogScope(); var prevCurrentFunction = currentFunction; currentFunction = func; try { if (func.SelfType != SelfParamType.None) { var p = func.Parameters[0]; if (p.Name == null) { p.Name = new AstIdExpr("self", false, p.Location); } if (func.ImplBlock.TargetType is StructType @struct) { ComputeStructMembers(@struct.Declaration); foreach (var m in @struct.Declaration.Members) { AstExpression expr = new AstDotExpr(new AstSymbolExpr(p), new AstIdExpr(m.Name, false, p.Location), p.Location); expr.AttachTo(func, func.SubScope); expr = InferType(expr, m.Type); // define use if no parameter has the same name if (!func.Parameters.Any(pa => pa.Name?.Name == m.Name)) { var(ok, other) = func.SubScope.DefineUse(m.Name, expr, false, out var use); if (!ok) { ReportError(p, $"A symbol with name '{m.Name}' already exists", ("Other here:", other)); } } } } } if (func.IsGeneric) { return; } if (func.TryGetDirective("linkname", out var ln)) { if (ln.Arguments.Count != 1) { ReportError(ln, $"#linkname requires exactly one argument!"); } else { var arg = ln.Arguments[0]; arg.SetFlag(ExprFlags.ValueRequired, true); arg = ln.Arguments[0] = InferType(arg, null); if (!(arg.Value is string)) { ReportError(arg, $"Argument to #linkname must be a constant string!"); } } } // define parameters foreach (var p in func.Parameters) { p.ContainingFunction = func; if (p.Name != null) { var(ok, other) = func.SubScope.DefineSymbol(p); if (!ok) { ReportError(p, $"Duplicate parameter '{p.Name}'", ("Other parameter here:", other)); } } if (p.DefaultValue != null) { p.DefaultValue.Scope = func.Scope; p.DefaultValue = InferTypeHelper(p.DefaultValue, p.Type, new TypeInferenceContext { TypeOfExprContext = p.Type }); ConvertLiteralTypeToDefaultType(p.DefaultValue, p.Type); p.DefaultValue = CheckType(p.DefaultValue, p.Type); if (p.DefaultValue.Type != p.Type && !p.DefaultValue.Type.IsErrorType) { ReportError(p.DefaultValue, $"The type of the default value ({p.DefaultValue.Type}) does not match the type of the parameter ({p.Type})"); } } } if (func.ReturnTypeExpr != null) { func.ReturnTypeExpr.Mutable = true; } if (func.ReturnTypeExpr?.Name != null) { func.ReturnTypeExpr.ContainingFunction = func; func.ReturnTypeExpr.IsReturnParam = true; var(ok, other) = func.SubScope.DefineSymbol(func.ReturnTypeExpr); if (!ok) { ReportError(func.ReturnTypeExpr, $"A symbol with name '{func.ReturnTypeExpr.Name.Name}' already exists in current scope", ("Other symbol here:", other)); } } else if (func.ReturnTypeExpr != null) { func.SubScope.DefineSymbol(func.ReturnTypeExpr, ".ret"); } if (func.ReturnTypeExpr?.TypeExpr is AstTupleExpr t) { int index = 0; foreach (var m in t.Types) { if (m.Name == null) { continue; } m.Mutable = true; AstExpression access = new AstArrayAccessExpr(new AstSymbolExpr(func.ReturnTypeExpr), new AstNumberExpr(index, Location: func.ReturnTypeExpr.Location), func.ReturnTypeExpr.Location); access = InferType(access, null); var(ok, other) = func.SubScope.DefineUse(m.Name.Name, access, false, out var use); if (!ok) { ReportError(m, $"A symbol with name '{m.Name.Name}' already exists in current scope", ("Other symbol here:", other)); } m.Symbol = use; ++index; } } if (func.FunctionType.IsErrorType || func.FunctionType.IsPolyType) { return; } if (func.Body != null && !func.IsMacroFunction) { var errs = PushSilentErrorHandler(); func.Body.AttachTo(func, func.SubScope); InferType(func.Body, null); if (func.ReturnTypeExpr != null && !func.Body.GetFlag(ExprFlags.Returns)) { // TODO: check that all return values are set var ret = new AstReturnStmt(null, new Location(func.Body.End)); ret.Scope = func.Body.SubScope; ret = AnalyseReturnStatement(ret); func.Body.Statements.Add(ret); func.Body.SetFlag(ExprFlags.Returns, true); } PopErrorHandler(); if (errs.HasErrors) { if (func.IsPolyInstance && func.InstantiatedAt != null) { ReportError($"Errors in polymorphic function '{func.Name}':"); errs.ForwardErrors(CurrentErrorHandler); void ReportSources(AstFuncExpr func, string indent = "") { if (func.InstantiatedAt == null) { return; } foreach (var loc in func.InstantiatedAt) { ReportError(loc, indent + $"Failed to instantiate function '{func.Name}'"); } foreach (var loc in func.InstantiatedBy) { ReportError(loc, indent + $"Failed to instantiate function '{func.Name}'"); ReportSources(loc, indent + " "); } } ReportError($"Caused from invocations here:"); ReportSources(func); } else { errs.ForwardErrors(CurrentErrorHandler); } } else { PassVariableLifetimes(func); } } } finally { currentFunction = prevCurrentFunction; PopLogScope(); Log($"Finished function {func.Name}"); } }
public override string VisitDotExpr(AstDotExpr dot, int data = 0) { return($"{dot.Left?.Accept(this, 0)}.{dot.Right.Accept(this)}"); }