diff --git a/examples/hydro/input.h2o b/examples/hydro/input.h2o new file mode 100644 index 0000000..71ba6b6 --- /dev/null +++ b/examples/hydro/input.h2o @@ -0,0 +1,8 @@ +module main +using std.io.read +main body + push string "prompt > " + push funcp std.io.read prompt + call + push funcp std.io.print println + call diff --git a/src/hydro/frontend/parser.rs b/src/hydro/frontend/parser.rs index 640b420..826c512 100644 --- a/src/hydro/frontend/parser.rs +++ b/src/hydro/frontend/parser.rs @@ -527,8 +527,7 @@ impl Parser { _ => Err("Unexpected value for boolean type".to_string()), }, "string" => { - let bytes = value_lexeme.clone().into_bytes().iter().skip(1).take(value_lexeme.len() - 2).map(|x| Value::Unsigned8(*x)).collect::>(); - Ok(Value::Array(Array::create(Type::Unsigned8, Box::new(Value::Unsigned64((value_lexeme.len() - 2) as u64)), bytes))) + Ok(Value::string(value_lexeme[1..(value_lexeme.len()-1)].to_string())) } "u8" => match value_lexeme.parse::() { Ok(value) => Ok(Value::Unsigned8(value)), diff --git a/src/hydro/intrinsic/intrinsicmanager.rs b/src/hydro/intrinsic/intrinsicmanager.rs index 56bfb28..b405230 100644 --- a/src/hydro/intrinsic/intrinsicmanager.rs +++ b/src/hydro/intrinsic/intrinsicmanager.rs @@ -3,6 +3,9 @@ use crate::hydro::executioncontext::ExecutionContext; use crate::hydro::value::Value; use lazy_static::lazy_static; use std::collections::HashMap; +use std::error::Error; +use std::io; +use std::io::Write; // TODO This way kinda sucks a lot and the name implies it would handle code output for non-vm intrinsic functions @@ -22,6 +25,8 @@ impl IntrinsicManager { manager.add_map("print", print); manager.add_map("println", println); + manager.add_map("flush", flush); + manager.add_map("readline", readline); manager } @@ -31,7 +36,11 @@ impl IntrinsicManager { } pub fn call(&self, intrinsic_name: String, execution_context: &ExecutionContext, arguments: Vec) -> Result, Exception> { - self.mapping[&intrinsic_name](execution_context, arguments) + if self.mapping.contains_key(&intrinsic_name) { + self.mapping[&intrinsic_name](execution_context, arguments) + } else { + Err(Exception::new(execution_context.clone(), format!("Intrinsic '{}' is undefined :(", intrinsic_name).as_str())) + } } } @@ -52,3 +61,26 @@ fn println(context: &ExecutionContext, args: Vec) -> Result, E Ok(Vec::new()) } } + +fn flush(context: &ExecutionContext, args: Vec) -> Result, Exception> { + if args.len() != 0 { + Err(Exception::new(context.clone(), format!("Expected 0 arguments for readline but got {}", args.len()).as_str())) + } else { + match io::stdout().flush() { + Ok(()) => Ok(Vec::new()), + Err(io_error) => Err(Exception::new(context.clone(), io_error.to_string().as_str())) + } + } +} + +fn readline(context: &ExecutionContext, args: Vec) -> Result, Exception> { + if args.len() != 0 { + Err(Exception::new(context.clone(), format!("Expected 0 arguments for readline but got {}", args.len()).as_str())) + } else { + let mut input = String::new(); + match io::stdin().read_line(&mut input) { + Ok(_) => Ok(vec![Value::string(input)]), + Err(io_error) => Err(Exception::new(context.clone(), io_error.to_string().as_str())) + } + } +} \ No newline at end of file diff --git a/src/hydro/value.rs b/src/hydro/value.rs index 11fc2df..6b20c72 100644 --- a/src/hydro/value.rs +++ b/src/hydro/value.rs @@ -141,6 +141,11 @@ pub enum Value { } impl Value { + pub fn string(value: String) -> Value { + let bytes = value.clone().into_bytes().iter().map(|x| Value::Unsigned8(*x)).collect::>(); + Value::Array(Array::create(Type::Unsigned8, Box::new(Value::Unsigned64(value.len() as u64)), bytes)) + } + pub fn type_of(&self) -> Type { match self { Value::Boolean(_) => Type::Boolean, diff --git a/standard_libraries/hydro/std/io/print.h2o b/standard_libraries/hydro/std/io/print.h2o index 685d1ac..f1c9df7 100644 --- a/standard_libraries/hydro/std/io/print.h2o +++ b/standard_libraries/hydro/std/io/print.h2o @@ -5,6 +5,9 @@ intrinsic print any body intrinsic println any body target vm "println" +intrinsic flush body + target vm "flush" + module main using std.io.print main body diff --git a/standard_libraries/hydro/std/io/read.h2o b/standard_libraries/hydro/std/io/read.h2o new file mode 100644 index 0000000..130213a --- /dev/null +++ b/standard_libraries/hydro/std/io/read.h2o @@ -0,0 +1,16 @@ +module std.io.read +using std.io.print +intrinsic readchar body + target vm "readchar" + +intrinsic readline body + target vm "readline" + +function prompt string body + push funcp std.io.print print + call + push funcp std.io.print flush + call + push funcp this readline + call + return \ No newline at end of file