Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 37 additions & 7 deletions examples/snake/Game.jack
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Game {
static int FPS, FRAMES_PER_TICK;
static String msg_game_over;
static String msg_game_over, msg_game_paused;
static int some_prime_num;

field int key, tick, game_counter, GAME_STATE, apple_coords, score;
Expand All @@ -11,6 +11,7 @@ class Game {
let FPS = 60;
let FRAMES_PER_TICK = FPS / 30;
let msg_game_over = "=== Game Over! ===";
let msg_game_paused = "=== Pause ===";
let GAME_STATE = 0;
let score = 0;
let ui = UI.new();
Expand All @@ -27,13 +28,11 @@ class Game {
let GAME_STATE = 1;

while (~(GAME_STATE = 0)) {
do Screen.clearScreen();
do ui.init();
do redraw();
let tick = 0;
let score = 0;
let snake = Snake.new(30, 20);
let apple_coords = placeApple(snake);
do UI.drawIngameMenu(score);
do run();
}
return;
Expand All @@ -47,6 +46,13 @@ class Game {
return;
}

method void redraw() {
do Screen.clearScreen();
do ui.init();
do UI.drawIngameMenu(score);
return;
}

method int run() {
var char tempKey; // the key currently pressed by the user
var boolean exit;
Expand All @@ -58,10 +64,11 @@ class Game {

while (~exit) {
let tempKey = Keyboard.keyPressed();
if (~(tempKey = 0)) {
if (~(tempKey = 0) & ~(tempKey = key)) {
let key = tempKey;
}
if (key = 81) { let exit = true; let GAME_STATE = 0; return GAME_STATE; } // q key
if (key = 80) { do pauseLoop(tick); } // p key

let is_over = tickGame();
do UI.updateIngameMenu(score);
Expand Down Expand Up @@ -124,15 +131,38 @@ class Game {
return;
}

method void pauseLoop(int tick_initial) {
var char key;
let GAME_STATE = 3;
do UI.drawPanel(200, 100, msg_game_paused);
while (GAME_STATE = 3) {
let key = Keyboard.keyPressed();
if (
// p key
(key = 80) &
((tick - tick_initial) > 10)
) {
let GAME_STATE = 1;
let key = 0;
do Sys.wait(200);
do redraw();
return;
}
do Sys.wait(1000 / FPS);
let tick = tick + 1;
}
return;
}

method int placeApple(Snake snake) {
var int oldPlace;
if (~(snake.getHead() = apple_coords)) {
return apple_coords;
}
let oldPlace = apple_coords;
let oldPlace = Utils.modulo(oldPlace + some_prime_num, UI.getBoardIndexSize() - 1);
let oldPlace = Utils.modulo((oldPlace + some_prime_num) * tick, UI.getBoardIndexSize() - 1);
while (snake.isCollided(oldPlace)) {
let oldPlace = Utils.modulo(oldPlace + some_prime_num, UI.getBoardIndexSize() - 1);
let oldPlace = Utils.modulo((oldPlace + some_prime_num) * tick, UI.getBoardIndexSize() - 1);
}
return oldPlace;
}
Expand Down
6 changes: 3 additions & 3 deletions examples/snake/UI.jack
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,6 @@ class UI {

function void updateScore(int score) {
var String s;
if (score = last_score) {
return;
}
let s = "SCORE: ";
do Output.moveCursor(0, 0);
do Output.printString(s);
Expand All @@ -168,6 +165,9 @@ class UI {
}

function void drawIngameMenu(int score) {
if (score = last_score) {
return;
}
do UI.updateScore(score);
return;
}
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ name = "parser"
[[bin]]
name = "compiler"

[dependencies]
vm = { path = "../vm" }

[dev-dependencies]
insta = { version = "^1.8.0", features = ["glob"] }
115 changes: 99 additions & 16 deletions src/compiler/src/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,114 @@
pub fn write_pop(seg: &str, index: u16) -> String {
format!("pop {} {}", seg, index)
use vm::instruction::{PushPop, PushPopInstruction};

use crate::instruction::Instruction;

#[derive(Clone, Debug)]
pub struct CompilerInstruction {
instruction: Instruction,
}

#[derive(Clone, Debug)]
pub struct WriteInst {
instruction: CompilerInstruction,
}

impl WriteInst {
pub fn new(instruction: CompilerInstruction) -> Self {
Self { instruction }
}

pub fn code(&self) -> String {
self.instruction.code()
}

pub fn instruction(&self) -> &Instruction {
&self.instruction.instruction
}
}

impl CompilerInstruction {
pub fn new(instruction: Instruction) -> Self {
Self { instruction }
}

#[allow(unreachable_patterns)]
pub fn code(&self) -> String {
match &self.instruction {
Instruction::Arithmetic(op) => op.into(),
Instruction::PushPop(PushPopInstruction {
segment,
addr: index,
inst_type,
}) => match inst_type {
PushPop::Push => format!("push {} {}", segment, index),
PushPop::Pop => format!("pop {} {}", segment, index),
},
Instruction::Label(label, _) => format!("label {}", label),
Instruction::Goto(label, _) => format!("goto {}", label),
Instruction::IfGoto(label, _) => format!("if-goto {}", label),
Instruction::Function(name, n_locals) => format!("function {} {}", name, n_locals),
Instruction::Return() => "return".to_string(),
Instruction::Call(name, n_args) => format!("call {} {}", name, n_args),
_ => unreachable!("Unreachable instruction: {:?}", self.instruction),
}
}
}

pub fn write_arith(op: &str) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::Arithmetic(op.into())))
}

pub fn write_not() -> WriteInst {
write_arith("not")
}

pub fn write_pop(seg: &str, index: u16) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::PushPop(
PushPopInstruction::new(PushPop::Pop, seg.into(), index),
)))
}

pub fn write_push(seg: &str, index: u16) -> String {
format!("push {} {}", seg, index)
pub fn write_push(seg: &str, index: u16) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::PushPop(
PushPopInstruction::new(PushPop::Push, seg.into(), index),
)))
}

pub fn write_function(name: String, n_locals: u16) -> String {
format!("function {} {}", name, n_locals)
pub fn write_function(name: String, n_locals: u16) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::Function(
name,
n_locals.into(),
)))
}

pub fn write_call<S: std::fmt::Display>(name: S, n_args: usize) -> String {
format!("call {} {}", name, n_args)
pub fn write_call<S: std::fmt::Display>(name: S, n_args: usize) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::Call(
name.to_string(),
n_args,
)))
}

pub fn write_return() -> String {
"return".to_string()
pub fn write_return() -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::Return()))
}

pub fn write_label<S: std::fmt::Display>(label: S) -> String {
format!("label {}", label)
pub fn write_label<S: std::fmt::Display>(label: S) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::Label(
label.to_string(),
None,
)))
}

pub fn write_if<S: std::fmt::Display>(label: S) -> String {
format!("if-goto {}", label)
pub fn write_if<S: std::fmt::Display>(label: S) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::IfGoto(
label.to_string(),
None,
)))
}

pub fn write_goto<S: std::fmt::Display>(label: S) -> String {
format!("goto {}", label)
pub fn write_goto<S: std::fmt::Display>(label: S) -> WriteInst {
WriteInst::new(CompilerInstruction::new(Instruction::Goto(
label.to_string(),
None,
)))
}
Loading