public InstructionBinder(AstBodyBuilder bodyBuilder, ImmutableDictionary <int, AstLocal> addressToLocalMap, int ramStart) { this.bodyBuilder = bodyBuilder; this.addressToLocalMap = addressToLocalMap; this.addressToLabelMap = new Dictionary <int, AstLabel>(); this.ramStart = ramStart; }
public static GlulxFunction Read(Memory memory, int address, int ramStart) { var scanner = memory.CreateScanner(address); var type = ReadType(scanner); var bodyBuilder = new AstBodyBuilder(); var addressToLocalMap = ReadLocals(scanner, bodyBuilder); var binder = new InstructionBinder(bodyBuilder, addressToLocalMap, ramStart); ReadBody(scanner, binder); var body = bodyBuilder.ToBody(); return(new GlulxFunction(type, address, body)); }
public void return_add_expression() { var builder = new AstBodyBuilder(); var label = builder.NewLabel(); builder.MarkLabel(label); builder.Return( AstFactory.ConstantExpression(19).Plus(23)); var function = new TestFunction(builder.ToBody()); var machine = new TestMachine(); var interpreter = new Interpreter(machine); var result = interpreter.Evaluate(function); Assert.Equal(42u, result); }
private static ImmutableDictionary <int, AstLocal> ReadLocals(MemoryScanner scanner, AstBodyBuilder bodyBuilder) { var map = ImmutableDictionary.CreateBuilder <int, AstLocal>(); var address = 0; while (true) { var sizeByte = scanner.NextByte(); var countByte = scanner.NextByte(); if (sizeByte == 0 && countByte == 0) { break; } var size = SizeByteToValueSize(sizeByte); // The Glulx spec states that locals will have padding to bring values // to their natural alignment. We should account for that here. Note that // the spec guarantees that the locals will start at a 4-byte boundary. if (size != ValueSize.Byte && address % sizeByte != 0) { address += sizeByte; } for (int i = 0; i < countByte; i++) { var local = bodyBuilder.DeclareLocal(size); map.Add(address, local); address += sizeByte; } } return(map.ToImmutable()); }