//Validates a built-in class definition and compile a built-in member private void CompileBuiltinMember(ElaBuiltinKind kind, ElaTypeClass s, int memIndex, LabelMap map) { var flags = ElaVariableFlags.Builtin | ElaVariableFlags.ClassFun; if (memIndex > s.Members.Count - 1) { AddError(ElaCompilerError.InvalidBuiltinClassDefinition, s, s.BuiltinName); return; } var m = s.Members[memIndex]; CompileBuiltin(kind, m, map, m.Name); AddLinePragma(m); PopVar(AddVariable(m.Name, m, flags, (Int32)kind)); }
void TypeClass() { var tc = default(ElaTypeClass); scanner.InjectBlock(); Expect(46); tc = new ElaTypeClass(t); tc.And = Program.Classes; Program.Classes = tc; Expect(2); var nm = default(String); tc.Name = t.val; if (la.kind == 54) { Get(); Expect(2); tc.BuiltinName=t.val; Expect(55); } var targ = String.Empty; Expect(1); targ = t.val; Expect(43); if (la.kind == 1) { Get(); nm=t.val; } else if (StartOf(20)) { Operators(); nm=t.val; } else if (la.kind == 54) { Get(); if (StartOf(20)) { Operators(); } else if (la.kind == 1) { Get(); } else SynErr(107); nm=t.val; Expect(55); } else SynErr(108); var count = 0; var mask = 0; if (la.kind == 1) { Get(); } else if (la.kind == 53) { Get(); } else SynErr(109); BuildMask(ref count, ref mask, t.val, targ); while (la.kind == 24) { Get(); if (la.kind == 1) { Get(); } else if (la.kind == 53) { Get(); } else SynErr(110); BuildMask(ref count, ref mask, t.val, targ); } tc.Members.Add(new ElaClassMember(t) { Name = nm, Components = count, Mask = mask }); while (StartOf(21)) { if (la.kind == 1) { Get(); nm=t.val; } else if (StartOf(20)) { Operators(); nm=t.val; } else { Get(); if (StartOf(20)) { Operators(); } else if (la.kind == 1) { Get(); } else SynErr(111); nm=t.val; Expect(55); } count = 0; mask = 0; if (la.kind == 1) { Get(); } else if (la.kind == 53) { Get(); } else SynErr(112); BuildMask(ref count, ref mask, t.val, targ); while (la.kind == 24) { Get(); if (la.kind == 1) { Get(); } else if (la.kind == 53) { Get(); } else SynErr(113); BuildMask(ref count, ref mask, t.val, targ); } tc.Members.Add(new ElaClassMember(t) { Name = nm, Components = count, Mask = mask }); } EndBlock(); }
//Built-in class compilation simply compiles an appropriate built-in and creates //an entry for a class as for a regular class private TypeClass CompileBuiltinClass(ElaTypeClass s, LabelMap map) { var tc = TypeClassHelper.GetTypeClass(s.BuiltinName); switch (tc) { case TypeClass.Eq: CompileBuiltinMember(ElaBuiltinKind.Equal, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.NotEqual, s, 1, map); break; case TypeClass.Ord: CompileBuiltinMember(ElaBuiltinKind.Greater, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.Lesser, s, 1, map); CompileBuiltinMember(ElaBuiltinKind.GreaterEqual, s, 2, map); CompileBuiltinMember(ElaBuiltinKind.LesserEqual, s, 3, map); CompileMember(s.Members[4]); break; case TypeClass.Additive: CompileBuiltinMember(ElaBuiltinKind.Add, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.Subtract, s, 1, map); CompileBuiltinMember(ElaBuiltinKind.Negate, s, 2, map); break; case TypeClass.Ring: CompileBuiltinMember(ElaBuiltinKind.Multiply, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.Power, s, 1, map); break; case TypeClass.Field: CompileBuiltinMember(ElaBuiltinKind.Divide, s, 0, map); break; case TypeClass.Modulo: CompileBuiltinMember(ElaBuiltinKind.Modulus, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.Remainder, s, 1, map); break; case TypeClass.Bit: CompileBuiltinMember(ElaBuiltinKind.BitwiseAnd, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.BitwiseOr, s, 1, map); CompileBuiltinMember(ElaBuiltinKind.BitwiseXor, s, 2, map); CompileBuiltinMember(ElaBuiltinKind.BitwiseNot, s, 3, map); CompileBuiltinMember(ElaBuiltinKind.ShiftLeft, s, 4, map); CompileBuiltinMember(ElaBuiltinKind.ShiftRight, s, 5, map); break; case TypeClass.Seq: CompileBuiltinMember(ElaBuiltinKind.Head, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.Tail, s, 1, map); CompileBuiltinMember(ElaBuiltinKind.IsNil, s, 2, map); break; case TypeClass.Len: CompileBuiltinMember(ElaBuiltinKind.Length, s, 0, map); break; case TypeClass.Ix: CompileBuiltinMember(ElaBuiltinKind.GetValue, s, 0, map); break; case TypeClass.Name: CompileBuiltinMember(ElaBuiltinKind.GetField, s, 0, map); CompileBuiltinMember(ElaBuiltinKind.HasField, s, 1, map); break; case TypeClass.Cat: CompileBuiltinMember(ElaBuiltinKind.Concat, s, 0, map); break; case TypeClass.Show: CompileBuiltinMember(ElaBuiltinKind.Show, s, 0, map); break; default: AddError(ElaCompilerError.InvalidBuiltinClass, s, s.BuiltinName); break; } return tc; }
//The main method for class compilation private void CompileClass(ElaTypeClass s, LabelMap map) { var tc = TypeClass.None; //We a special syntax for built-in classes and they are compiled separately if (s.BuiltinName != null) tc = CompileBuiltinClass(s, map); else { //Run through members and create global class functions (Newfunc) for (var i = 0; i < s.Members.Count; i++) CompileMember(s.Members[i]); } //We create a special variable that will be initialized with a global unique ID of this class var sa = AddVariable("$$$" + s.Name, s, ElaVariableFlags.None, (Int32)tc); cw.Emit(Op.Classid, AddString(s.Name)); PopVar(sa); //Some validation if (frame.InternalClasses.ContainsKey(s.Name)) AddError(ElaCompilerError.ClassAlreadyDeclared, s, s.Name); else frame.InternalClasses.Add(s.Name, new ClassData(s.Members.ToArray())); if (s.And != null) CompileClass(s.And, map); }