public void ShouldBeAppliedIfFunctionDoesNotEndWithReturn() { const string name = "test"; var funcAst = new AstMemberFunction(name, new List <Parameter>(), new Position(0, 0)); funcAst.Expressions.Add( new AstFunctionCall("println", new List <AstExpression> { new AstBinaryMathOperation(BinaryMath.Plus, new AstIntegerConstant(5, null), new AstIntegerConstant(5, null), null) }, null)); funcAst.Expressions.Add( new AstFunctionCall("println", new List <AstExpression> { new AstStringConstant("hello world", null) }, null) ); var klass = new AstClass(name, null); klass.Functions.Add(funcAst); var env = new ScriptEnvironment(new OperationCodeFactory(), new ValueFactory()); Compiler.Compile(env, new AstRoot(new Position(0, 0)) { Classes = { klass } }); Assert.Equal(typeof(Return), env.Classes[GetGlobalName(name)].Functions[name].Code.Last().Op.GetType()); }
public void ShouldBeAppliedIfFunctionIsEmpty() { const string name = "test"; var funcAst = new AstMemberFunction(name, new List <Parameter>(), new Position(0, 0)); var klass = new AstClass(name, null); klass.Functions.Add(funcAst); var env = new ScriptEnvironment(new OperationCodeFactory(), new ValueFactory()); Compiler.Compile(env, new AstRoot(new Position(0, 0)) { Classes = { klass } }); Assert.Equal(typeof(Return), env.Classes[GetGlobalName(name)].Functions[name].Code.Last().Op.GetType()); }
public SemanticAtom Visit(AstClass n) { var baseClassUtilizedType = n.ClassExtension?.Accept(this) as UtilizedType; var c = new Class(n.Name, baseClassUtilizedType, n.Location); AddToGlobalUtilization(baseClassUtilizedType, s => { c.BaseClass = s as Class; }); foreach (var v in n.ClassDeclarationList.OfType <Property>()) { var p = (ClassProperty)v.Accept(this); if (c.Properties.ContainsKey(p.Name)) { Globals.Errors.Add($"[{p.DeclarationLocation.StartLine}, {p.DeclarationLocation.StartColumn}] Property ({p.Name}) is already defined in {c.Name}."); } else { c.Properties.Add(p.Name, p); } } foreach (var m in n.ClassDeclarationList.OfType <Method>()) { var method = (ClassMethod)m.Accept(this); method.OwnerClass = c; if (c.Methods.ContainsKey(method.Name)) { Globals.Errors.Add($"[{method.DeclarationLocation.StartLine}, {method.DeclarationLocation.StartColumn}] Method ({method.Name}) is already defined in {c.Name}."); } else { c.Methods.Add(method.Name, method); } } AddToTypeTable(c); return(c); }
public void Visit(AstClass n) { Helpers.Write(_tab); Helpers.WriteColor("class ", ConsoleColor.DarkCyan, ConsoleColor.Black); Helpers.WriteColor(n.Name, ConsoleColor.Green, ConsoleColor.Black); n.ClassExtension?.Accept(this); Helpers.WriteLine(" { "); Tab(); foreach (var v in n.ClassDeclarationList.OfType <Property>()) { v.Accept(this); Helpers.WriteLine(); } foreach (var m in n.ClassDeclarationList.OfType <Method>()) { m.Accept(this); Helpers.WriteLine(); } Untab(); Helpers.WriteLine($"{_tab}}}"); }
public void Visit(AstClass n) { Helpers.WriteLine($"{_tab}{n.Text} ({n.Name}) [{n.Location.StartLine}, {n.Location.StartColumn}]"); Tab(); n.ClassExtension?.Accept(this); Helpers.WriteLine($"{_tab}Variables"); Tab(); foreach (var v in n.ClassDeclarationList.OfType <Property>()) { v.Accept(this); } Untab(); Helpers.WriteLine($"{_tab}Methods"); Tab(); foreach (var m in n.ClassDeclarationList.OfType <Method>()) { m.Accept(this); } Untab(); Untab(); }
AstClass FlattenClass(AstClass astClass, List <string> parentSources, IEnumerable <AstBlockMember> parentItems) { AstClass result; if (_flattenedClasses.TryGetValue(astClass, out result)) { return(result); } var partials = new List <AstClass>(); foreach (var item in parentItems) { var cd = item as AstClass; if (cd != null && cd.Modifiers.HasFlag(Modifiers.Partial) && cd.Name.Symbol == astClass.Name.Symbol) { if (astClass.OptionalGeneric != null && cd.OptionalGeneric == null || cd.OptionalGeneric != null && astClass.OptionalGeneric == null) { continue; } if (astClass.OptionalGeneric != null && astClass.OptionalGeneric.Parameters.Count != cd.OptionalGeneric.Parameters.Count) { continue; } partials.Add(cd); } } Modifiers modifiers = 0; string comment = null; var attributes = new List <AstAttribute>(); var swizzlerTypes = new List <AstExpression>(); var baseTypes = new List <AstExpression>(); var items = new List <AstBlockMember>(); foreach (var part in partials) { modifiers |= part.Modifiers; comment = comment ?? part.DocComment; attributes.AddRange(part.Attributes); swizzlerTypes.AddRange(part.Swizzlers); baseTypes.AddRange(part.Bases); items.AddRange(part.Members); } IReadOnlyList <AstIdentifier> genericParameters = null; IReadOnlyList <AstConstraint> genericConstraints = null; if (astClass.OptionalGeneric != null) { genericParameters = astClass.OptionalGeneric.Parameters; genericConstraints = astClass.OptionalGeneric.Constraints; } foreach (var part in partials) { if (part.Type != astClass.Type) { Log.Error(part.Name.Source, ErrorCode.E0000, "All partials must be either 'class', 'struct' or 'interface'"); } var partProtection = part.Modifiers & Modifiers.ProtectionModifiers; if (partProtection != 0 && partProtection != (modifiers & Modifiers.ProtectionModifiers)) { Log.Error(part.Name.Source, ErrorCode.E3025, "Partial class cannot have conflicting protection modifier"); } if (part.Modifiers.HasFlag(Modifiers.Sealed) && modifiers.HasFlag(Modifiers.Abstract)) { Log.Error(part.Name.Source, ErrorCode.E0000, "Partial class cannot specify 'sealed', because it is declared 'abstract' somewhere else"); } else if (part.Modifiers.HasFlag(Modifiers.Abstract) && modifiers.HasFlag(Modifiers.Sealed)) { Log.Error(part.Name.Source, ErrorCode.E0000, "Partial class cannot specify 'abstract', because it is declared 'sealed' somewhere else"); } if (part.OptionalCondition != null) { Log.Error(part.Name.Source, ErrorCode.E0000, "Partial class does not support 'extern(CONDITION)'"); } if (part.OptionalGeneric != null && part != astClass) { for (int i = 0; i < genericParameters.Count; i++) { if (part.OptionalGeneric.Parameters[i].Symbol != genericParameters[i].Symbol) { Log.Error(part.Name.Source, ErrorCode.E3027, "Partial generic class must use the same type parameter names in the same order"); } } if (part.OptionalGeneric.Constraints.Count != 0) { // TODO: C# does not have this limitation if (genericConstraints.Count == 0) { genericConstraints = part.OptionalGeneric.Constraints; } else { Log.Error(part.Name.Source, ErrorCode.E3027, "Only one of the partials may specify generic constraints"); } } } } result = new AstClass( comment, attributes, modifiers, null, astClass.Type, astClass.Name, baseTypes, astClass.OptionalGeneric != null ? new AstGenericSignature(genericParameters, genericConstraints) : null, items, swizzlerTypes); foreach (var part in partials) { parentSources.Add(part.Name.Source.FullPath); if (_flattenedClasses.ContainsKey(part)) { Log.Error(part.Name.Source, ErrorCode.E0000, "Found more than one partial master definition for: " + part.Name.Symbol); continue; } _flattenedClasses.Add(part, result); } return(result); }
public void Visit(AstClass n) { // Unneeded. throw new NotImplementedException(); }
public override bool Visit(AstClass node) { Log(node.ToString()); return true; }
private void CompileClass(AstClass node, Syt syt, StringBuilder sb) { syt.Add(Ksyte.Class, node.StName, node.StName); CompileRecursive(node.RgclassDecl, syt, sb); foreach (var astSubroutine in node.Rgsubroutine) { Ksyte ksyte; switch (astSubroutine.Ksubroutine) { case Ksubroutine.Constructor: ksyte = Ksyte.Constructor; break; case Ksubroutine.MemberFunction: ksyte = Ksyte.MemberFunction; break; case Ksubroutine.StaticFunction: ksyte = Ksyte.StaticFunction; break; default: throw new ArgumentOutOfRangeException(); } syt.Add(ksyte, astSubroutine.StName, null); } CompileRecursive(node.Rgsubroutine, syt, sb); }
void PopulateClass(AstClass astClass, DataType result) { var parameterizedType = Parameterize(result); var fieldInitializers = new List <AstExpression>(); var deferredActions = new List <Action>(); parameterizedType.AssignBaseType(); parameterizedType.Base?.PopulateMembers(); foreach (var it in result.Interfaces) { it.PopulateMembers(); } // Create dummies for members foreach (var item in astClass.Members) { if (item is AstClassMember) { var m = (AstClassMember)item; if (!_compiler.Environment.Test(((item as AstNamedMember)?.Name ?? astClass.Name).Source, m.OptionalCondition)) { continue; } } switch (item.MemberType) { case AstMemberType.Method: { var md = item as AstMethod; ClassType gt = null; if (md.OptionalGenericSignature != null) { gt = new ClassType(md.Name.Source, parameterizedType, md.DocComment, Modifiers.Private | Modifiers.Static | Modifiers.Generated, md.Name.Symbol); CreateGenericSignature(gt, md.OptionalGenericSignature, md.Modifiers.HasFlag(Modifiers.Override) || md.OptionalInterfaceType != null); } var pl = _compiler.CompileParameterList(gt ?? parameterizedType, md.Parameters, deferredActions); var rt = _resolver.GetType(gt ?? parameterizedType, md.ReturnType); var me = new Method(md.Name.Source, result, md.DocComment, GetMemberModifiers(md.Name.Source, parameterizedType, md.Modifiers), md.Name.Symbol, gt, rt, pl); result.Methods.Add(me); if (md.Attributes.Count > 0) { EnqueueAttributes(me, x => me.SetAttributes(_compiler.CompileAttributes(parameterizedType, md.Attributes))); } gt?.Methods.Add(me); EnqueueCompiler(new FunctionCompiler(_compiler, me, parameterizedType, md.OptionalBody)); if (md.OptionalInterfaceType != null) { var it = _resolver.GetType(parameterizedType, md.OptionalInterfaceType); if (!it.IsInvalid) { var im = TryImplementMethod(it, me); if (im == null) { Log.Error(md.OptionalInterfaceType.Source, ErrorCode.E0000, "Method " + (me.UnoName + me.Parameters.BuildString()).Quote() + " does not exist in interface " + it.Quote()); } else { me.SetImplementedMethod(im); } } } break; } case AstMemberType.Constructor: { var md = item as AstConstructor; var pl = _compiler.CompileParameterList(parameterizedType, md.Parameters, deferredActions); var ctor = new Constructor(md.Source, result, md.DocComment, md.Modifiers, pl); if (md.Attributes.Count > 0) { EnqueueAttributes(ctor, x => ctor.SetAttributes(_compiler.CompileAttributes(parameterizedType, md.Attributes))); } var fc = new FunctionCompiler(_compiler, ctor, parameterizedType, md.OptionalBody); EnqueueCompiler(fc); if (ctor.IsStatic) { if (result.Initializer != null) { Log.Error(ctor.Source, ErrorCode.E3002, parameterizedType.Quote() + " already has a static constructor"); } result.Initializer = ctor; } else { ctor.Modifiers = GetMemberModifiers(md.Source, parameterizedType, md.Modifiers); result.Constructors.Add(ctor); } if (md.OptionalBody != null) { ctor.SetBody(new Scope(ctor.Source)); } if (md.CallType == AstConstructorCallType.This && parameterizedType.IsStruct && md.CallArguments.Count == 0) { ctor.Body.Statements.Add(new StoreThis(ctor.Source, new Default(ctor.Source, parameterizedType))); } else if (md.CallType != AstConstructorCallType.None) { if (ctor.Body == null) { Log.Error(md.Source, ErrorCode.E0000, ctor.Quote() + " cannot call constructor without method body"); } else if (md.CallType != AstConstructorCallType.Base || parameterizedType.Base != DataType.Invalid) { _enqueuedActions.Add(() => { var bt = md.CallType == AstConstructorCallType.Base ? parameterizedType.Base : parameterizedType; bt.PopulateMembers(); Constructor callCtor; Expression[] callArgs; if (!fc.TryResolveConstructorOverload(md.Source, bt.Constructors, md.CallArguments, out callCtor, out callArgs)) { Log.Error(md.Source, ErrorCode.E3003, bt.Quote() + " does not have a constructor that matches this argument list"); } else { ctor.Body.Statements.Add(new CallConstructor(md.Source, callCtor, callArgs)); } }); } } else if (!ctor.IsStatic && parameterizedType.Base != null && parameterizedType.TypeType != TypeType.Struct && ctor.Body != null) { _enqueuedActions.Add(() => { Constructor callCtor; Expression[] callArgs; if (!fc.TryResolveConstructorOverload(md.Source, parameterizedType.Base.Constructors, AstArgument.Empty, out callCtor, out callArgs)) { Log.Error(md.Source, ErrorCode.E3004, "Base class " + parameterizedType.Base.Quote() + " does not have a default constructor"); } else { ctor.Body.Statements.Add(new CallConstructor(md.Source, callCtor, callArgs)); } }); } break; } case AstMemberType.Finalizer: { var fd = item as AstFinalizer; var pl = _compiler.CompileParameterList(parameterizedType, fd.Parameters, deferredActions); var finalizer = new Finalizer(fd.Source, result, fd.DocComment, fd.Modifiers, pl); if (fd.Attributes.Count > 0) { EnqueueAttributes(finalizer, x => finalizer.SetAttributes(_compiler.CompileAttributes(parameterizedType, fd.Attributes))); } if (result.Finalizer != null) { Log.Error(fd.Source, ErrorCode.E3002, parameterizedType.Quote() + " already has a finalizer"); } result.Finalizer = finalizer; EnqueueCompiler(new FunctionCompiler(_compiler, finalizer, parameterizedType, fd.OptionalBody)); break; } case AstMemberType.Property: { var pd = item as AstProperty; var dt = _resolver.GetType(parameterizedType, pd.ReturnType); var prop = new Property(pd.Name.Source, pd.DocComment, GetMemberModifiers(pd.Name.Source, parameterizedType, pd.Modifiers), pd.Name.Symbol, result, dt); result.Properties.Add(prop); bool hasImplicitImplementation = false; // Implicit implementation if (!prop.IsAbstract) { if (pd.Get != null && pd.Get.OptionalBody == null || pd.Set != null && pd.Set.OptionalBody == null) { if (pd.Set != null && pd.Set.OptionalBody == null && (pd.Get == null || pd.Get?.OptionalBody != null)) { if (!prop.IsExtern) { Log.Error(pd.Set.Source, ErrorCode.E3042, prop.Quote(".set") + " must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors"); } } else if (pd.Get != null && pd.Get.OptionalBody == null && (pd.Set == null || pd.Set?.OptionalBody != null)) { if (!prop.IsExtern) { Log.Error(pd.Get.Source, ErrorCode.E3041, prop.Quote(".get") + " must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors"); } } else { prop.CreateImplicitField(prop.Source); var getScope = new Scope(pd.Get.Source); prop.CreateGetMethod(pd.Get.Source, GetAccessorModifiers(pd.Get.Source, prop, pd.Get.Modifiers) | Modifiers.Generated, getScope); var setScope = new Scope(pd.Set.Source); var setMethod = prop.CreateSetMethod(pd.Set.Source, GetAccessorModifiers(pd.Set.Source, prop, pd.Set.Modifiers) | Modifiers.Generated, setScope); var propIndex = result.Properties.Count - 1; _enqueuedActions.Add(() => { parameterizedType.PopulateMembers(); var obj = prop.Modifiers.HasFlag(Modifiers.Static) ? null : new This(prop.Source, parameterizedType).Address; var field = parameterizedType.Properties[propIndex].ImplicitField; getScope.Statements.Add( new Return(pd.Get.Source, new LoadField(pd.Get.Source, obj, field))); setScope.Statements.Add( new StoreField(pd.Set.Source, obj, field, new LoadArgument(pd.Set.Source, setMethod, 0))); }); hasImplicitImplementation = true; } } } if (pd.Attributes.Count > 0) { EnqueueAttributes(prop, x => { prop.SetAttributes(_compiler.CompileAttributes(parameterizedType, pd.Attributes)); prop.GetMethod?.SetAttributes(prop.Attributes); prop.SetMethod?.SetAttributes(prop.Attributes); prop.ImplicitField?.SetAttributes(prop.Attributes); }); } if (!hasImplicitImplementation) { if (pd.Get != null) { EnqueueCompiler(new FunctionCompiler(_compiler, prop.CreateGetMethod(pd.Get.Source, GetAccessorModifiers(pd.Get.Source, prop, pd.Get.Modifiers)), parameterizedType, pd.Get.OptionalBody)); } if (pd.Set != null) { EnqueueCompiler(new FunctionCompiler(_compiler, prop.CreateSetMethod(pd.Set.Source, GetAccessorModifiers(pd.Set.Source, prop, pd.Set.Modifiers)), parameterizedType, pd.Set.OptionalBody)); } } if (pd.OptionalInterfaceType != null) { var it = _compiler.NameResolver.GetType(parameterizedType, pd.OptionalInterfaceType); if (!it.IsInvalid) { var im = TryImplementProperty(it, prop); if (im == null) { Log.Error(pd.OptionalInterfaceType.Source, ErrorCode.E0000, "Property " + prop.UnoName.Quote() + " does not exist in interface " + it.Quote()); } else { prop.SetImplementedProperty(im); } } } break; } case AstMemberType.Field: { var f = item as AstField; var dt = _compiler.NameResolver.GetType(parameterizedType, f.ReturnType); if (f.FieldModifiers.HasFlag(FieldModifiers.Const)) { var m = new Literal(f.Name.Source, result, f.Name.Symbol, f.DocComment, GetMemberModifiers(f.Name.Source, parameterizedType, f.Modifiers), dt, f.InitValue); result.Literals.Add(m); if (f.Attributes.Count > 0) { EnqueueAttributes(m, x => m.SetAttributes(_compiler.CompileAttributes(parameterizedType, f.Attributes))); } if (f.InitValue == null) { Log.Error(f.Name.Source, ErrorCode.E3007, "'const' fields must provide a constant value"); } else { deferredActions.Add(() => m.Value = _compiler.CompileConstant(f.InitValue, parameterizedType, dt).Value); } } else { var m = new Field(f.Name.Source, result, f.Name.Symbol, f.DocComment, GetMemberModifiers(f.Name.Source, parameterizedType, f.Modifiers), f.FieldModifiers, dt); fieldInitializers.Add(f.InitValue); result.Fields.Add(m); if (f.Attributes.Count > 0) { EnqueueAttributes(m, x => m.SetAttributes(_compiler.CompileAttributes(parameterizedType, f.Attributes))); } } break; } case AstMemberType.Operator: { var od = item as AstOperator; var rt = _resolver.GetType(parameterizedType, od.ReturnType); var pl = _compiler.CompileParameterList(parameterizedType, od.Parameters, deferredActions); var op = new Operator(od.Source, result, od.Operator, od.DocComment, GetMemberModifiers(od.Source, parameterizedType, od.Modifiers), rt, pl); result.Operators.Add(op); if (od.Attributes.Count > 0) { EnqueueAttributes(op, x => op.SetAttributes(_compiler.CompileAttributes(parameterizedType, od.Attributes))); } EnqueueCompiler(new FunctionCompiler(_compiler, op, parameterizedType, od.OptionalBody)); break; } case AstMemberType.Converter: { var cd = item as AstConverter; var rt = _resolver.GetType(parameterizedType, cd.TargetType); var pl = _compiler.CompileParameterList(parameterizedType, cd.Parameters, deferredActions); var type = cd.Modifiers.HasFlag(Modifiers.Implicit) ? CastModifier.Implicit : CastModifier.Explicit; var cast = new Cast(cd.TargetType.Source, result, type, cd.DocComment, GetMemberModifiers(cd.TargetType.Source, parameterizedType, cd.Modifiers), rt, pl); result.Casts.Add(cast); if (cd.Attributes.Count > 0) { EnqueueAttributes(cast, x => cast.SetAttributes(_compiler.CompileAttributes(parameterizedType, cd.Attributes))); } EnqueueCompiler(new FunctionCompiler(_compiler, cast, parameterizedType, cd.OptionalBody)); break; } case AstMemberType.Indexer: { var id = item as AstIndexer; var rt = _resolver.GetType(parameterizedType, id.ReturnType); var pl = _compiler.CompileParameterList(parameterizedType, id.Parameters, deferredActions); var indexer = new Property(id.Source, id.DocComment, GetMemberModifiers(id.Source, parameterizedType, id.Modifiers), "Item", result, rt, pl); result.Properties.Add(indexer); if (id.Attributes.Count > 0) { EnqueueAttributes(indexer, x => { indexer.SetAttributes(_compiler.CompileAttributes(parameterizedType, id.Attributes)); indexer.GetMethod?.SetAttributes(indexer.Attributes); indexer.SetMethod?.SetAttributes(indexer.Attributes); }); } if (id.Get != null) { EnqueueCompiler(new FunctionCompiler(_compiler, indexer.CreateGetMethod(id.Get.Source, GetAccessorModifiers(id.Get.Source, indexer, id.Get.Modifiers)), parameterizedType, id.Get.OptionalBody)); } if (id.Set != null) { EnqueueCompiler(new FunctionCompiler(_compiler, indexer.CreateSetMethod(id.Set.Source, GetAccessorModifiers(id.Set.Source, indexer, id.Set.Modifiers)), parameterizedType, id.Set.OptionalBody)); } if (id.OptionalInterfaceType != null) { var it = _resolver.GetType(parameterizedType, id.OptionalInterfaceType); if (!it.IsInvalid) { var im = TryImplementProperty(it, indexer); if (im == null) { Log.Error(id.OptionalInterfaceType.Source, ErrorCode.E0000, "Indexer 'this" + indexer.Parameters.BuildString("[", "]") + "' does not exist in interface " + it.Quote()); } else { indexer.SetImplementedProperty(im); } } } break; } case AstMemberType.Event: { var ed = item as AstEvent; var dt = _resolver.GetType(parameterizedType, ed.DelegateType); if (dt.IsInvalid) { break; } if (!dt.IsDelegate) { Log.Error(ed.Name.Source, ErrorCode.E3012, "Events must have delegate type. " + dt + " is a " + dt.TypeType); } var ev = new Event(ed.Name.Source, ed.DocComment, GetMemberModifiers(ed.Name.Source, parameterizedType, ed.Modifiers), result, dt, ed.Name.Symbol); result.Events.Add(ev); if (ed.Attributes.Count > 0) { EnqueueAttributes(ev, x => { ev.SetAttributes(_compiler.CompileAttributes(parameterizedType, ed.Attributes)); ev.AddMethod?.SetAttributes(ev.Attributes); ev.RemoveMethod?.SetAttributes(ev.Attributes); ev.ImplicitField?.SetAttributes(ev.Attributes); }); } // Implicit implementation if (ed.Add == null && ed.Remove == null) { if (!ev.IsAbstract) { ev.CreateImplicitField(ed.Name.Source); var addScope = new Scope(ed.Name.Source); var addMethod = ev.CreateAddMethod(ev.Source, ev.Modifiers | Modifiers.Generated, addScope); var removeScope = new Scope(ed.Name.Source); var removeMethod = ev.CreateRemoveMethod(ev.Source, ev.Modifiers | Modifiers.Generated, removeScope); var eventIndex = result.Events.Count - 1; _enqueuedActions.Add(() => { parameterizedType.PopulateMembers(); var obj = ev.IsStatic ? null : new This(ev.Source, parameterizedType).Address; var field = parameterizedType.Events[eventIndex].ImplicitField; addScope.Statements.Add( new StoreField(ev.Source, obj, field, new CastOp(ev.Source, ev.ReturnType, _ilf.CallMethod(ev.Source, _ilf.Essentials.Delegate, "Combine", new CastOp(ev.Source, _ilf.Essentials.Delegate, new LoadField(ev.Source, obj, field)), new LoadArgument(ev.Source, addMethod, 0))))); removeScope.Statements.Add( new StoreField(ev.Source, obj, field, new CastOp(ev.Source, ev.ReturnType, _ilf.CallMethod(ev.Source, _ilf.Essentials.Delegate, "Remove", new CastOp(ev.Source, _ilf.Essentials.Delegate, new LoadField(ev.Source, obj, field)), new LoadArgument(ev.Source, removeMethod, 0))))); }); } else { ev.CreateAddMethod(ev.Source, ev.Modifiers); ev.CreateRemoveMethod(ev.Source, ev.Modifiers); } break; } if (ed.Add != null && ed.Add.Modifiers != 0 || ed.Remove != null && ed.Remove.Modifiers != 0) { Log.Error(ed.Name.Source, ErrorCode.E3040, "Modifiers can not be placed on event accessor declarations"); } if (ed.Add != null) { EnqueueCompiler(new FunctionCompiler(_compiler, ev.CreateAddMethod(ed.Add.Source, ev.Modifiers), parameterizedType, ed.Add.OptionalBody)); } if (ed.Remove != null) { EnqueueCompiler(new FunctionCompiler(_compiler, ev.CreateRemoveMethod(ed.Remove.Source, ev.Modifiers), parameterizedType, ed.Remove.OptionalBody)); } if (ed.OptionalInterfaceType != null) { var it = _resolver.GetType(parameterizedType, ed.OptionalInterfaceType); if (!it.IsInvalid) { var im = TryImplementEvent(it, ev); if (im == null) { Log.Error(ed.OptionalInterfaceType.Source, ErrorCode.E0000, "Event " + ev.UnoName.Quote() + " does not exist in interface " + it.Quote()); } else { ev.SetImplementedEvent(im); } } } break; } } switch (item.MemberType) { case AstMemberType.Method: case AstMemberType.Property: case AstMemberType.Indexer: case AstMemberType.Event: switch (parameterizedType.TypeType) { case TypeType.Class: case TypeType.Interface: case TypeType.Struct: continue; } break; case AstMemberType.Field: case AstMemberType.Constructor: case AstMemberType.Operator: case AstMemberType.Converter: case AstMemberType.Class: case AstMemberType.Enum: case AstMemberType.Delegate: switch (parameterizedType.TypeType) { case TypeType.Class: case TypeType.Struct: continue; } break; case AstMemberType.Finalizer: case AstMemberType.MetaMethod: case AstMemberType.MetaProperty: case AstMemberType.NodeBlock: case AstMemberType.Block: case AstMemberType.ApplyStatement: switch (parameterizedType.TypeType) { case TypeType.Class: continue; } break; } Log.Error(((item as AstNamedMember)?.Name ?? astClass.Name).Source, ErrorCode.E3013, "<" + item.MemberType + "> is not allowed in this scope"); } // Compile swizzle types if (astClass.Swizzlers != null) { foreach (var e in astClass.Swizzlers) { result.Swizzlers.Add(_resolver.GetType(parameterizedType, e)); } } // Compile field initializers if (fieldInitializers.Count > 0) { _enqueuedActions.Add(() => CompileFieldInitializers(result, parameterizedType, fieldInitializers)); } // Create default constructor in non-static classes if (result.IsClass && !result.IsStatic && result.Constructors.Count == 0) { var ctor = new Constructor(parameterizedType.Source, parameterizedType, null, (parameterizedType.IsAbstract ? Modifiers.Protected : Modifiers.Public) | Modifiers.Generated, ParameterList.Empty, new Scope(parameterizedType.Source)); result.Constructors.Add(ctor); _enqueuedActions.Add(() => { parameterizedType.AssignBaseType(); parameterizedType.Base.PopulateMembers(); Constructor callCtor = null; Expression[] callArgs = null; if (parameterizedType.Base != DataType.Invalid && !new FunctionCompiler(_compiler, parameterizedType).TryResolveConstructorOverload(parameterizedType.Source, parameterizedType.Base.Constructors, AstArgument.Empty, out callCtor, out callArgs)) { Log.Error(parameterizedType.Source, ErrorCode.E3001, parameterizedType.Base.Quote() + " does not have a default constructor"); } else { ctor.Body.Statements.Add(new CallConstructor(ctor.Source, callCtor, callArgs)); } }); } // Resolve overridden members foreach (var m in result.Methods) { m.SetOverriddenMethod(TryOverrideMethod(m)); if (m.IsGenericDefinition) { if (m.ImplementedMethod != null || m.OverriddenMethod != null) { // Inherit base generic constraints var baseParams = (m.OverriddenMethod ?? m.ImplementedMethod).GenericDefinition.GenericParameters; for (int i = 0; i < m.GenericParameters.Length; i++) { var baseParam = baseParams[i]; var thisParam = m.GenericParameters[i]; baseParam.AssignBaseType(); thisParam.AssignBaseType(); thisParam.SetBase(baseParam.Base); thisParam.SetConstraintType(baseParam.ConstraintType); thisParam.SetInterfaces(baseParam.Interfaces); if (baseParam.Constructors.Count > 0) { thisParam.Constructors.Add(new Constructor(baseParam.Constructors[0].Source, thisParam, null, Modifiers.Public | Modifiers.Generated | Modifiers.Extern, ParameterList.Empty)); } } } Parameterize(m.Source, m, m.GenericParameters); } } foreach (var m in result.Properties) { m.SetOverriddenProperty(TryOverrideProperty(m)); } foreach (var m in result.Events) { m.SetOverriddenEvent(TryOverrideEvent(m)); } if (!result.IsInterface && result.Interfaces.Length > 0) { ImplementInterfaces(result); } _compiler.BlockBuilder.PopulateBlock(astClass, result.Block); foreach (var action in deferredActions) { action(); } }
public SemanticAtom Visit(AstClass n) { throw new NotImplementedException(); }
public void CreateClass(AstClass astClass, Namescope parent, IEnumerable <AstBlockMember> parentItems) { var sources = new List <string>(); if (astClass.Modifiers.HasFlag(Modifiers.Partial)) { astClass = FlattenClass(astClass, sources, parentItems); } DataType result; if (_cachedClasses.TryGetValue(astClass, out result)) { return; } var src = astClass.Name.Source; var modifiers = GetTypeModifiers(parent, astClass.Modifiers); switch (astClass.Type) { case AstClassType.Struct: result = new StructType(src, parent, astClass.DocComment, modifiers, astClass.Name.Symbol); break; case AstClassType.Class: result = new ClassType(src, parent, astClass.DocComment, modifiers, astClass.Name.Symbol); break; case AstClassType.Interface: if (modifiers.HasFlag(Modifiers.Abstract)) { Log.Error(src, ErrorCode.E0000, "'abstract' is not valid for interface"); } result = new InterfaceType(src, parent, astClass.DocComment, modifiers | Modifiers.Abstract, astClass.Name.Symbol); break; default: Log.Error(src, ErrorCode.I3045, "<" + astClass.Type + "> is not a class, struct or interface type"); return; } if (parent is DataType) { (parent as DataType).NestedTypes.Add(result); } else if (parent is Namespace) { (parent as Namespace).Types.Add(result); } else { Log.Error(result.Source, ErrorCode.I3046, "<" + astClass.Type + "> is not allowed in this context"); } _cachedClasses.Add(astClass, result); if (astClass.OptionalGeneric != null) { CreateGenericSignature(result, astClass.OptionalGeneric, false); } result.SetBlock(new Block(src, result, null, result.Modifiers & Modifiers.ProtectionModifiers, ".block")); foreach (var s in sources) { result.SourceFiles.Add(s); } foreach (var b in astClass.Members) { if (b is AstBlockBase) { _compiler.AstProcessor.CreateBlock(b as AstBlockBase, result, astClass.Members); } } if (astClass.Attributes.Count > 0) { EnqueueAttributes(result, x => { result.SetAttributes(_compiler.CompileAttributes(result.Parent, astClass.Attributes)); // Remove default constructor if TargetSpecificType if (result.HasAttribute(_ilf.Essentials.TargetSpecificTypeAttribute) && result.Constructors.Count == 1 && result.Constructors[0].IsGenerated) { result.Constructors.Clear(); } }); } EnqueueType(result, x => CompileBaseTypes(x, astClass.Bases), x => PopulateClass(astClass, x)); }
private AstClass ParseClass() { var _class = new AstClass(); Expect(Ktoken.Class); _class.StName = Expect(Ktoken.Id).St; Expect(Ktoken.Lbrace); _class.RgclassDecl = ParseRgClassDecl().ToArray(); _class.Rgsubroutine = ParseRgSubroutine().ToArray(); Expect(Ktoken.Rbrace); Expect(Ktoken.Eof); return _class; }