Skip to content
Merged
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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ values (when appropriate). The REPL will always print the value
returned by the last command.

The `@` command duplicates the value at the top of the stack and
pushes the duplicate. The `$` command will push a `nil`.
pushes the duplicate. The `$` command will push a `nil`. The
`#` command swaps the two elements at the top of the stack.

To push an element onto the stack, use the `push` command. To
pop the top element, one may use the `pop` command. Note also
Expand Down Expand Up @@ -95,6 +96,8 @@ equivalent to:
rz | @inflate | mount | load /platform/oxide/kernel/amd64/unix | call
```

## Commands

The reader supports a handful of "reader commands":

* `clear` clears the terminal window
Expand Down Expand Up @@ -126,6 +129,10 @@ Supported commands include:
entry point.
* `loadmem <addr>,<len>` to load an ELF object from the given
region of memory.
* `call <location> [<up to 6 args>]` calls the System V ABI
compliant function at `<location>`, passing up to six
arguments taken from the environment stack argument list
terminated by nil.
* `rdmsr <u32>` to read the numbered MSR (note some MSRs can be
specified by name, such as `IA32_APIC_BASE`).
* `wrmsr <u32> <u64>` to write the given value to the given MSR.
Expand Down
25 changes: 21 additions & 4 deletions src/repl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ fn evalcmd(
"outw" => pio::outw(config, env),
"peek" => memory::read(config, env),
"poke" => memory::write(config, env),
"pop" => Ok(popenv(env)),
"pop" => Ok(pop2(env)),
"push" => Ok(Value::Nil),
"rdmsr" => msr::read(config, env),
"rdsmn" => smn::read(config, env),
Expand All @@ -276,24 +276,43 @@ fn dup(env: &mut Vec<Value>) -> Value {
}
}

fn swaptop(env: &mut [Value]) -> Value {
let len = env.len();
if len > 1 {
env.swap(len - 1, len - 2);
env[len - 1].clone()
} else {
Value::Nil
}
}

fn popenv(env: &mut Vec<Value>) -> Value {
if let Some(v) = env.pop() { v } else { Value::Nil }
}

fn pop2(env: &mut Vec<Value>) -> Value {
popenv(env);
popenv(env)
}

fn eval(
config: &mut bldb::Config,
cmd: &reader::Command,
env: &mut Vec<Value>,
) -> Result<Value> {
match cmd {
reader::Command::Push => Ok(dup(env)),
reader::Command::Swap => Ok(swaptop(env)),
reader::Command::Cmd(_, tokens) => {
let mut tokens = tokens.clone();
while let Some(token) = tokens.pop() {
match token {
reader::Token::Push => {
dup(env);
}
reader::Token::Swap => {
swaptop(env);
}
reader::Token::Term => env.push(Value::Nil),
reader::Token::Value(v) => env.push(v),
}
Expand All @@ -304,9 +323,7 @@ fn eval(
match evalcmd(config, &cmd, env)? {
Value::Nil => Ok(Value::Nil),
v => {
if &cmd != "pop" {
env.push(v.clone());
}
env.push(v.clone());
Ok(v)
}
}
Expand Down
36 changes: 30 additions & 6 deletions src/repl/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ use core::fmt;
#[derive(Clone, Debug)]
pub enum Token {
Push,
Swap,
Term,
Value(Value),
}

#[derive(Clone)]
pub enum Command {
Push,
Swap,
Cmd(String, Vec<Token>),
}

Expand All @@ -32,6 +34,7 @@ impl fmt::Debug for Command {
) -> core::result::Result<(), fmt::Error> {
match self {
Self::Push => write!(f, "Push"),
Self::Swap => write!(f, "Swap"),
Self::Cmd(cmd, _) => write!(f, "{cmd}"),
}
}
Expand Down Expand Up @@ -159,21 +162,35 @@ pub fn read(
for cmd in cs {
let mut cmd = cmd.trim();
let cmdline = String::from(cmd);
while let Some(rest) = cmd.strip_prefix("@") {
cmds.push(Command::Push);
cmd = rest.trim();
while !cmd.is_empty() {
if let Some(rest) = cmd.strip_prefix("@") {
cmds.push(Command::Push);
cmd = rest.trim();
continue;
}
if let Some(rest) = cmd.strip_prefix("#") {
cmds.push(Command::Swap);
cmd = rest.trim();
continue;
}
break;
}
let mut tokens = Vec::<Token>::new();
for mut tok in cmd.split_ascii_whitespace() {
while !tok.is_empty() {
if let Some(rest) = tok.strip_prefix("@") {
tokens.push(Token::Push);
tok = rest;
tok = rest.trim();
continue;
}
if let Some(rest) = tok.strip_prefix("#") {
tokens.push(Token::Swap);
tok = rest.trim();
continue;
}
if let Some(rest) = tok.strip_prefix("$") {
tokens.push(Token::Term);
tok = rest;
tok = rest.trim();
continue;
}
tokens.push(Token::Value(parse_value(tok)?));
Expand Down Expand Up @@ -225,7 +242,8 @@ values (when appropriate). The REPL will always print the value
returned by the last command.

The `@` command duplicates the value at the top of the stack and
pushes the duplicate. The `$` command will push a `nil`.
pushes the duplicate. The `$` command will push a `nil`. The
`#` command swaps the two elements at the top of the stack.

To push an element onto the stack, use the `push` command. To
pop the top element, one may use the `pop` command. Note also
Expand Down Expand Up @@ -265,6 +283,8 @@ equivalent to:
rz | @inflate | mount | load /platform/oxide/kernel/amd64/unix | call
```

## Commands

The reader supports a handful of "reader commands":

* `clear` clears the terminal window
Expand Down Expand Up @@ -296,6 +316,10 @@ Supported commands include:
entry point
* `loadmem <addr>,<len>` to load an ELF object from the given
region of memory.
* `call <location> [<up to 6 args>]` calls the System V ABI
compliant function at `<location>`, passing up to six
arguments taken from the environment stack argument list
terminated by nil.
* `rdmsr <u32>` to read the numbered MSR (note some MSRs can be
specified by name, such as `IA32_APIC_BASE`)
* `wrmsr <u32> <u64>` to write the given value to the given MSR
Expand Down