Skip to content

Commit

Permalink
feat: stdio builtin functions
Browse files Browse the repository at this point in the history
  • Loading branch information
viddrobnic committed Jun 15, 2024
1 parent fe09a74 commit 1dc9c9c
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
51 changes: 50 additions & 1 deletion runtime/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fmt::Display, rc::Rc};
use std::{fmt::Display, io, rc::Rc};

use crate::{
error::ErrorKind,
Expand Down Expand Up @@ -26,6 +26,9 @@ pub enum Builtin {

Push,
Pop,

Print,
Input,
}

impl Display for Builtin {
Expand All @@ -45,6 +48,8 @@ impl Display for Builtin {
Builtin::Split => write!(f, "split"),
Builtin::Push => write!(f, "push"),
Builtin::Pop => write!(f, "pop"),
Builtin::Print => write!(f, "print"),
Builtin::Input => write!(f, "input"),
}
}
}
Expand All @@ -66,6 +71,8 @@ impl Builtin {
"split" => Self::Split,
"push" => Self::Push,
"pop" => Self::Pop,
"print" => Self::Print,
"input" => Self::Input,

_ => return None,
};
Expand Down Expand Up @@ -95,6 +102,9 @@ impl Builtin {

Builtin::Push => call_push(args),
Builtin::Pop => call_pop(args),

Builtin::Print => call_print(args),
Builtin::Input => call_input(args),
}
}
}
Expand Down Expand Up @@ -309,3 +319,42 @@ fn call_pop(args: &[Object]) -> Result<Object, ErrorKind> {
None => Ok(Object::Null),
}
}

fn call_print(args: &[Object]) -> Result<Object, ErrorKind> {
validate_args_len(args, 1)?;

match &args[0] {
Object::Null => println!("null"),
Object::Integer(val) => println!("{val}"),
Object::Float(val) => println!("{val}"),
Object::Boolean(val) => println!("{val}"),
Object::String(val) => println!("{val}"),

obj => {
return Err(ErrorKind::InvalidBuiltinArg {
builtin: Builtin::Print,
data_type: obj.into(),
})
}
}

Ok(Object::Null)
}

fn call_input(args: &[Object]) -> Result<Object, ErrorKind> {
validate_args_len(args, 0)?;

let mut line = String::new();
let read = io::stdin()
.read_line(&mut line)
.map_err(|_| ErrorKind::InputError)?;

if read == 0 {
// Handle eof
Ok(Object::Null)
} else {
// Remove \n that is always read
line.pop();
Ok(Object::String(Rc::new(line)))
}
}
2 changes: 2 additions & 0 deletions runtime/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub enum ErrorKind {
builtin: Builtin,
data_type: DataType,
},
InputError,
}

#[derive(Debug, Error, PartialEq)]
Expand Down Expand Up @@ -135,6 +136,7 @@ impl Display for ErrorKind {
ErrorKind::InvalidNrOfArgs { expected, got } => write!(f, "Invalid number of arguments, expected: {expected}, got: {got}"),

ErrorKind::InvalidBuiltinArg { builtin, data_type } => write!(f, "Can't call {builtin} on {data_type}."),
ErrorKind::InputError => write!(f, "Could not read from stdin"),
}
}
}
6 changes: 6 additions & 0 deletions runtime/src/test_input/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Test Input

This folder contains some files to test input and ouput.
These tests are not automated, because I didn't feel like dealing
with passing around reader and writer instead of calling stdin and stdout
directly.
12 changes: 12 additions & 0 deletions runtime/src/test_input/fibs.aoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fib = fn(n) {
if (n <= 2) {
1
} else {
fib(n-1) + fib(n-2)
}
}

for (n = input(); n; n = input()) {
print(fib(int(n)))
}

0 comments on commit 1dc9c9c

Please sign in to comment.