public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; if (valueType == ASTType.I8) // no conversion needed. { return(value); } IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I8); switch (valueType) { case ASTType.I4: tr.Instructions.Add(new IRInstruction(IROpCode.SX, retVar, value)); break; case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, value)); break; case ASTType.R4: case ASTType.R8: tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, retVar, value)); break; default: throw new NotSupportedException(); } return(retVar); }
public override string VisitASTType(ASTType astType) { var extensions = astType.Extensions.Select(e => $"{astType.Name} --|> {e}"); var fields = astType.Fields.Select(f => $@"{f.Name}: {string.Join(" ", f.Type.Select(t => t.Value))}").ToList(); var typeReferences = astType.Fields.Select(f => { var _type = f.Type.Last().Value; if (_type != "String" && _type != "Number") { return($@"{astType.Name} --* {_type}"); } else { return(""); } }); string template = $@" class {astType.Name} {{ {string.Join("\n", fields)} }} {string.Join("\n", extensions)} {string.Join("\n", typeReferences)} "; this.Parts.Add(template); return(template); }
/// <summary> /// Resolve the imports of this module. Here we'll /// link multiple files together. This is not part /// of the compiler, but part of the project system. /// TODO: verify this approach! /// </summary> private void ResolveImports() { this.Imports = new List <IASTNode>(); var imports = Generator.AST.FindAll(n => n is ASTImport).ToList(); imports.ForEach(node => { ASTImport import = (ASTImport)node; var ast = this.Project.GetAstForModule(import.Name); if (!import.Imports.Any()) { var copies = ast .FindAll(a => a is ASTType || a is ASTAlias || a is ASTData || a is ASTChoice) .Select(a => { return(a switch { ASTType t => ObjectCopier.Clone(t) as IASTNode, ASTAlias t => ObjectCopier.Clone(t) as IASTNode, ASTData t => ObjectCopier.Clone(t) as IASTNode, ASTChoice t => ObjectCopier.Clone(t) as IASTNode, _ => throw new Exception("Can only serialize real AST nodes.") }); }) .ToList(); this.Imports.AddRange(copies); }
public override string VisitASTType(ASTType astType) { var typeDescription = $@"From module: <a href=""/index.html?path=preview&module={astType.Module}"" target='_parent'>{astType.Module}</a> {string.Join(" ", astType.Annotations.Select(a => a.Value).ToList()).Trim()}"; return($@" <div class=""table-container""> <table> <thead> <tr> <th colspan=""5"">{astType.Name}</th> </tr> <tr class=""description""> <th colspan=""5"">{typeDescription}</th> </tr> <tr> <th>Name</th> <th>Type</th> <th>Required</th> <th>Restrictions</th> <th>Description</th> </tr> </thead> <tbody> {String.Join(Environment.NewLine, astType.Fields.Select(Visit).ToList())} <tbody> </table> </div> "); }
public void BasicParserTest() { var code = @" type Person = @ The First Name of the Person FirstName: String; "; var tokens = new Lexer().Lex(code); var parseTree = new Parser(tokens).Parse(); Assert.NotNull(parseTree); List <IASTNode> list = parseTree.ToList(); Assert.Single(list); ASTType t = list[0] as ASTType; Assert.Equal("Person", t.Name); Assert.Empty(t.Parameters); Assert.Single(t.Fields); ASTTypeField field = t.Fields.First(); Assert.Single(field.Annotations); Assert.True(field.Annotations.First() is ASTAnnotation); Assert.Equal("The First Name of the Person", field.Annotations.First().Value); Assert.Equal("FirstName", field.Name); Assert.Equal(Helpers.ToTypeDefinition(new [] { "String" }), field.Type); }
public override XmlSchemaObject VisitASTType(ASTType astType) { var t = new XmlSchemaComplexType { Name = astType.Name }; var fields = astType.Fields.Select(Visit); var all = new XmlSchemaAll(); foreach (var field in fields) { all.Items.Add(field); } t.Particle = all; var description = string.Join(" ", astType.Annotations.Select(a => a.Value)); var schemaAnnotation = new XmlSchemaAnnotation(); var docs = new XmlSchemaDocumentation() { Markup = TextToNodeArray(description) }; schemaAnnotation.Items.Add(docs); t.Annotation = schemaAnnotation; this.Schema.Items.Add(t); ExtractElement(astType); return(t); }
public void FieldRestrictionsAnnotations() { var code = @" type Person = FirstName: String & min 2 @ Should not be 30 & max 30 ; "; var tokens = new Lexer().Lex(code); var parseTree = new Parser(tokens).Parse().ToList(); Assert.NotNull(parseTree); Assert.Single(parseTree); ASTType t = (ASTType)parseTree[0]; Assert.Single(t.Fields); Assert.Equal(2, t.Fields.First().Restrictions.Count()); ASTTypeField field = t.Fields.First(); Assert.Equal(2, field.Restrictions.Count()); Assert.Equal("Should not be 30", field.Restrictions.ToList()[1].Annotations.First().Value); }
public void MultipleTypes() { var code = @" type Person = @ The First Name of the Person @ A second Annotation is always cool to add FirstName: String; LastName: String; @ Age as a number is weird ofc! Age: Number; Addresses: List; type Address = Street: String; HouseNumber: Number; "; var tokens = new Lexer().Lex(code); var parseTree = new Parser(tokens).Parse().ToList(); Assert.NotNull(parseTree); Assert.Equal(2, parseTree.Count()); ASTType personType = parseTree[0] as ASTType; Assert.Equal("Person", personType.Name); ASTType addressType = parseTree[1] as ASTType; Assert.Equal("Address", addressType.Name); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I4); retVar.RawType = tr.Context.Method.Module.CorLibTypes.Byte; switch (valueType) { case ASTType.I4: case ASTType.I8: case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, value)); break; case ASTType.R4: case ASTType.R8: IRVariable tmp = tr.Context.AllocateVRegister(ASTType.I8); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, tmp, value)); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, tmp)); break; default: throw new NotSupportedException(); } return(retVar); }
public override string VisitASTType(ASTType astType) { return($@" <div class=""table-container""> <table> <thead> <tr> <th colspan=""4"">{astType.Name}</th> </tr> <tr class=""description""> <th colspan=""4"">{string.Join(" ", astType.Annotations.Select(a => a.Value).ToList())}</th> </tr> <tr> <th>Name</th> <th>Type</th> <th>Required</th> <th>Description</th> </tr> </thead> <tbody> {string.Join("\n", astType.Fields.Select(Visit).ToList())} <tbody> </table> </div> "); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; IRVariable retVar = tr.Context.AllocateVRegister(ASTType.R8); switch (valueType) { case ASTType.I4: IRVariable tmpVar = tr.Context.AllocateVRegister(ASTType.I8); tr.Instructions.Add(new IRInstruction(IROpCode.SX, tmpVar, value)); tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.FCONV, retVar, tmpVar)); break; case ASTType.I8: tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.FCONV, retVar, value)); break; default: throw new NotSupportedException(); } return(retVar); }
public override IEnumerable <Descriptor> VisitASTType(ASTType astType) { yield return(new Descriptor($"{astType.Name}") { Module = ModuleName, Name = astType.Name, Description = MapAnnotations(astType.Annotations), DescriptorType = DescriptorType.Type.ToString("g") }); foreach (var field in astType.Fields) { if (field.Module == ModuleName) { yield return(new Descriptor(field.Name) { Module = ModuleName, Name = field.Name, Description = MapAnnotations(field.Annotations), Parent = astType.Name, Type = MapTypes(field.Types), DescriptorType = DescriptorType.Field.ToString("g") }); } } }
public void Translate(IRInstruction instr, ILTranslator tr) { tr.PushOperand(instr.Operand1); tr.PushOperand(instr.Operand2); ASTType type = TypeInference.InferBinaryOp(instr.Operand1.Type, instr.Operand2.Type); switch (type) { case ASTType.I4: tr.Instructions.Add(new ILInstruction(ILOpCode.REM_DWORD)); break; case ASTType.I8: case ASTType.Ptr: tr.Instructions.Add(new ILInstruction(ILOpCode.REM_QWORD)); break; case ASTType.R4: tr.Instructions.Add(new ILInstruction(ILOpCode.REM_R32)); break; case ASTType.R8: tr.Instructions.Add(new ILInstruction(ILOpCode.REM_R64)); break; default: throw new NotSupportedException(); } tr.PopOperand(instr.Operand1); }
public static ILImmediate Create(object value, ASTType type) { return(new ILImmediate { Value = value, Type = type }); }
public override string VisitASTType(ASTType astType) { return(Intercept($@" public class {astType.Name} {{ {string.Join(Environment.NewLine, astType.Fields.Select(Visit))} }} ")); }
public ASTNode(Token op, ASTNode left, ASTNode right, ASTType type) { tokValue = new Token(); this.op = op; this.left = left; this.right = right; this.type = type; }
public ASTNode(Token token, ASTOperand operand) { Token = token; Priority = 0; Operand = operand; Type = operand.Type; Operator = ASTOperator.None; }
public override string VisitASTType(ASTType astType) { var extensions = astType.Extensions.Select(e => $"{astType.Name} --|> {e}"); var fields = astType.Fields.Select(f => $@"{f.Name}: {string.Join(" ", f.Types.Select(t => t.Value))}").ToList(); var typeReferences = astType.Fields.Select(f => { var _mod = f.Types.First().Value; var _type = f.Types.Last().Value; if (_type != "String" && _type != "Number" && _type != "Decimal" && _type != "Boolean" && _type != "Date" && _type != "DateTime" && _type != "Time" && !_type.StartsWith("'", StringComparison.Ordinal)) { if (_mod == "List") { var min = f.Restrictions.FirstOrDefault(r => r.Key == "min")?.Value ?? "0"; var max = f.Restrictions.FirstOrDefault(r => r.Key == "max")?.Value ?? "*"; return($@"{astType.Name} --o ""{min}..{max}"" {_type}"); } else { return($@"{astType.Name} --o {_type}"); } } else { return(""); } }); if (astType.Fields.Any()) { var template = $@" class {astType.Name} {{ {string.Join(Environment.NewLine, fields)} }} {string.Join(Environment.NewLine, extensions)} {string.Join(Environment.NewLine, typeReferences)} "; this.Parts.Add(template); return(template); } else { var template = $@" class {astType.Name} {string.Join(Environment.NewLine, extensions)} "; Parts.Add(template); return(template); } }
public static ASTType InferShiftOp(ASTType a, ASTType b) { if ((b == ASTType.Ptr || b == ASTType.I4) && (a == ASTType.I4 || b == ASTType.I4 || a == ASTType.Ptr)) { return(a); } throw new ArgumentException("Invalid Shift Op Operand Types."); }
public ASTNode(ASTType _type, string _rule, string _term, int _start, int _end, Dictionary <string, ASTNode> _childs) { Type = _type; RuleName = _rule; RuleTerm = _term; Text.IndexStart = _start; Text.IndexEnd = _end; Childs = _childs; }
public override IEnumerable <string> VisitASTType(ASTType astType) { yield return(astType.Name); foreach (var field in astType.Fields) { yield return(Visit(field).First()); } }
public ASTNode(Token token, ASTType type, long value) { Token = token; Type = type; Operator = ASTOperator.None; Operand = null; IValue = value; Computed = true; }
public ASTNode(ASTType _type, string _rule, string _term, int _start, int _end, string _value) { Type = _type; RuleName = _rule; RuleTerm = _term; Text.IndexStart = _start; Text.IndexEnd = _end; Text.Value = _value; Childs = new Dictionary <string, ASTNode>(); }
public ASTNode(ASTType _type, string _rule, string _term, int _start, int _end) { Parent = null; Type = _type; RuleName = _rule; RuleTerm = _term; Text.IndexStart = _start; Text.IndexEnd = _end; Childs = new Dictionary <string, ASTNode>(); }
public JSchema Create(ASTType astType, IEnumerable <IASTNode> nodes) { this.Nodes = nodes.ToList(); var schema = MapAstNode(astType.Name); schema.SchemaVersion = new Uri("http://json-schema.org/draft-07/schema#"); schema.Title = astType.Name; schema.Description = JsonMapper.Annotate(astType.Annotations); schema.ExtensionData.Add("references", References); return(schema); }
public void MultipleFieldsParserTest() { var code = @" type Person = @ The First Name of the Person @ A second Annotation is always cool to add FirstName: String; LastName: String; @ Age as a number is weird ofc! Age: Number; "; var tokens = new Lexer().Lex(code); var parseTree = new Parser(tokens).Parse(); Assert.NotNull(parseTree); List <IASTNode> list = parseTree.ToList(); Assert.Single(list); ASTType t = list[0] as ASTType; Assert.Equal("Person", t.Name); Assert.Empty(t.Parameters); Assert.Equal(3, t.Fields.Count()); List <ASTTypeField> fields = t.Fields.ToList(); ASTTypeField field = fields.First(); Assert.Equal(2, field.Annotations.Count()); Assert.True(field.Annotations.First() is ASTAnnotation); Assert.Equal("The First Name of the Person", field.Annotations.First().Value); Assert.Equal("A second Annotation is always cool to add", field.Annotations.ToList()[1].Value); Assert.Equal("FirstName", field.Name); Assert.Equal("String", field.Type.First().Value); ASTTypeField lastNameField = fields[1]; Assert.Equal("LastName", lastNameField.Name); Assert.Equal("String", lastNameField.Type.First().Value); Assert.Empty(lastNameField.Annotations); ASTTypeField ageField = fields[2]; Assert.Equal("Age", ageField.Name); Assert.Equal(new List <ASTTypeDefinition>() { new ASTTypeDefinition("Number") }, ageField.Type); Assert.Single(ageField.Annotations); }
public static void EmitCompareEq(IRTranslator tr, ASTType type, IIROperand a, IIROperand b) { if (type == ASTType.O || type == ASTType.ByRef || type == ASTType.R4 || type == ASTType.R8) { tr.Instructions.Add(new IRInstruction(IROpCode.CMP, a, b)); } else { // I4/I8/Ptr Debug.Assert(type == ASTType.I4 || type == ASTType.I8 || type == ASTType.Ptr); tr.Instructions.Add(new IRInstruction(IROpCode.CMP, a, b)); } }
public override string VisitASTType(ASTType astType) { if (!done.Contains(astType.Name)) { return($@" public interface {astType.Name} {{ {String.Join(Environment.NewLine, astType.Fields.Select(Visit).ToList())} }} "); } return(""); }
public IRVariable AllocateVRegister(ASTType type) { var vReg = new IRVariable { Id = vRegs.Count, Name = "vreg_" + vRegs.Count, Type = type, VariableType = IRVariableType.VirtualRegister }; vRegs.Add(vReg); return(vReg); }
public static ILOpCode GetSIND(ASTType type, TypeSig rawType) { if (rawType != null) { switch (rawType.ElementType) { case ElementType.I1: case ElementType.U1: case ElementType.Boolean: return(ILOpCode.SIND_BYTE); case ElementType.I2: case ElementType.U2: case ElementType.Char: return(ILOpCode.SIND_WORD); case ElementType.I4: case ElementType.U4: case ElementType.R4: return(ILOpCode.SIND_DWORD); case ElementType.I8: case ElementType.U8: case ElementType.R8: return(ILOpCode.SIND_QWORD); case ElementType.Ptr: case ElementType.I: case ElementType.U: return(ILOpCode.SIND_PTR); default: return(ILOpCode.SIND_OBJECT); } } switch (type) { case ASTType.I4: case ASTType.R4: return(ILOpCode.SIND_DWORD); case ASTType.I8: case ASTType.R8: return(ILOpCode.SIND_QWORD); case ASTType.Ptr: return(ILOpCode.SIND_PTR); default: return(ILOpCode.SIND_OBJECT); } }
public IRVariable AllocateVRegister(ASTType type) { var vReg = new IRVariable { Id = this.vRegs.Count, Name = $"vreg_{this.vRegs.Count}", Type = type, VariableType = IRVariableType.VirtualRegister }; this.vRegs.Add(vReg); return(vReg); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; IRVariable t = tr.Context.AllocateVRegister(ASTType.I4); IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I4); t.RawType = tr.Context.Method.Module.CorLibTypes.Int16; int rangechk = tr.VM.Runtime.VMCall.RANGECHK; int ckovf = tr.VM.Runtime.VMCall.CKOVERFLOW; switch (valueType) { case ASTType.I4: case ASTType.I8: case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(ushort.MinValue))); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(short.MaxValue))); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(rangechk), value)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ckovf))); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, t, value)); tr.Instructions.Add(new IRInstruction(IROpCode.SX, retVar, t)); break; case ASTType.R4: case ASTType.R8: IRVariable tmpVar = tr.Context.AllocateVRegister(ASTType.I8); IRVariable fl = tr.Context.AllocateVRegister(ASTType.I4); tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, tmpVar, value)); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = fl, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.OVERFLOW) }); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ckovf), fl)); value = tmpVar; goto case ASTType.I8; default: throw new NotSupportedException(); } return(retVar); }
public void ComputeSingle() { this.Type = this.Right.Type; if (!this.Right.Computed) return; switch (this.Operator) { case ASTOperator.Not: // FIXME check Right is a boolean this.BValue = !this.Right.BValue; break; case ASTOperator.Neg: return; default: throw new Exception(); } this.Computed = true; }
public ASTStatement PushInteger(Token token, ASTType type, long value) { ASTNode node = new ASTNode(token, type, value); addPostFixOperand(node); return this; }