public static Command FunctionCall( string name, int argc, LabelGenerator generator) { var label = generator.Generate("ret"); return(new Command( $"call {name} {argc}", new[] { label.Address, "D=A", "@R13", "M=D", '@' + argc.ToString(), "D=A", "@R14", "M=D", '@' + name, "D=A", "@R15", "M=D", "@CALL", "0;JMP", label.Declaration })); }
public Function(string fileName, string name, int argc) { FileName = fileName; Name = name; Argc = argc; LabelGenerator = new LabelGenerator(name); _commands.Add(Commands.DeclareFunction(name, argc)); }
private static IEnumerable <string> Bootstrapper() { var labelGenerator = new LabelGenerator("bootstrapper"); return(new[] { "@256", "D=A", "@SP", "M=D" }.Concat(Commands .FunctionCall("Sys.init", 0, labelGenerator).HackInstructions)); }
public static Command Parse(string fileName, string line, LabelGenerator generator) { var parts = line.Split(' '); var command = parts[0]; var arg1 = parts.Length > 1 ? parts[1] : null; var arg2 = parts.Length > 2 ? int.Parse(parts[2]) : 0; switch (command) { case "add": return(Commands.Arithmetic.Add()); case "sub": return(Commands.Arithmetic.Sub()); case "neg": return(Commands.Arithmetic.Neg()); case "and": return(Commands.Bitwise.And()); case "or": return(Commands.Bitwise.Or()); case "not": return(Commands.Bitwise.Not()); case "eq": return(Commands.Comparsion.Equal(generator)); case "gt": return(Commands.Comparsion.GreateThan(generator)); case "lt": return(Commands.Comparsion.LessThan(generator)); case "function": return(Commands.DeclareFunction(arg1, arg2)); case "call": return(Commands.FunctionCall(arg1, arg2, generator)); case "return": return(Commands.FunctionRetrun()); case "goto": return(Commands.Goto(arg1)); case "if-goto": return(Commands.IfGoto(arg1)); case "label": return(Commands.Label(arg1)); case "push": { switch (arg1) { case "constant": return(Commands.Push.Constant(arg2)); case "local": return(Commands.Push.Local(arg2)); case "argument": return(Commands.Push.Argument(arg2)); case "this": return(Commands.Push.This(arg2)); case "that": return(Commands.Push.That(arg2)); case "temp": return(Commands.Push.Temp(arg2)); case "pointer": return(Commands.Push.Pointer(arg2)); case "static": return(Commands.Push.Static(fileName, arg2)); default: throw new ArgumentException("Invalid segment"); } } case "pop": { switch (arg1) { case "local": return(Commands.Pop.Local(arg2)); case "argument": return(Commands.Pop.Argument(arg2)); case "this": return(Commands.Pop.This(arg2)); case "that": return(Commands.Pop.That(arg2)); case "temp": return(Commands.Pop.Temp(arg2)); case "pointer": return(Commands.Pop.Pointer(arg2)); case "static": return(Commands.Pop.Static(fileName, arg2)); default: throw new ArgumentException("Invalid segment"); } } default: throw new InvalidOperationException("Invalid command"); } }
public static Command LessThan(LabelGenerator generator) => Compare("lt", "JGT", generator.Generate("lt"));
public static Command GreateThan(LabelGenerator generator) => Compare("gt", "JLT", generator.Generate("gt"));
public static Command Equal(LabelGenerator generator) => Compare("eq", "JEQ", generator.Generate("eq"));