Add support for i32 variable type

This commit is contained in:
Sofia 2020-06-25 00:39:18 +03:00
parent 8b60677123
commit 8028dde855
7 changed files with 74 additions and 9 deletions

View File

@ -1,3 +1 @@
let otus = "Hello, world!"; let gotus = 3;
let dotus = otus;
print(dotus);

View File

@ -1,4 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::num::ParseIntError;
use super::errors::CompilerError; use super::errors::CompilerError;
use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Position, Statement}; use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Position, Statement};
@ -19,6 +20,7 @@ pub enum Command {
AssignVariable(HeapID, RegID), // Assign variable from registery at RegID AssignVariable(HeapID, RegID), // Assign variable from registery at RegID
VarToReg(HeapID, RegID), // Bring Variable to registery at RegID VarToReg(HeapID, RegID), // Bring Variable to registery at RegID
StringLit(String), // Bring String Literal to Stack StringLit(String), // Bring String Literal to Stack
I32Lit(i32), // Bring i32 Literal to Stack
FunctionCall(FuncID), // Call Function at FuncID FunctionCall(FuncID), // Call Function at FuncID
} }
@ -145,10 +147,25 @@ impl Compiler {
fn handle_literal(&mut self, pattern: LiteralPattern) -> Result<VariableType, CompilerError> { fn handle_literal(&mut self, pattern: LiteralPattern) -> Result<VariableType, CompilerError> {
match pattern { match pattern {
LiteralPattern::StringLit(string) => self.list.push(Command::StringLit(string)), LiteralPattern::StringLit(string) => {
} self.list.push(Command::StringLit(string));
Ok(VariableType::TypeString) Ok(VariableType::TypeString)
} }
LiteralPattern::Integer32Lit(string) => {
self.list.push(Command::I32Lit(Compiler::handle_parseint(
string.parse::<i32>(),
)?));
Ok(VariableType::TypeI32)
}
}
}
fn handle_parseint<T>(res: Result<T, ParseIntError>) -> Result<T, CompilerError> {
match res {
Ok(i) => Ok(i),
Err(err) => Err(CompilerError::ParseIntError(err)),
}
}
} }
#[derive(Default)] #[derive(Default)]

View File

@ -2,6 +2,7 @@ use super::parser::Position;
use std::fmt; use std::fmt;
use std::fmt::Display; use std::fmt::Display;
use std::io; use std::io;
use std::num::ParseIntError;
use super::vm::VariableType; use super::vm::VariableType;
@ -67,6 +68,7 @@ pub enum CompilerError {
LetFailed(Position, Box<CompilerError>), LetFailed(Position, Box<CompilerError>),
CanNotAssignVoidType, CanNotAssignVoidType,
FunctionNotFound(Position, String, Vec<VariableType>), FunctionNotFound(Position, String, Vec<VariableType>),
ParseIntError(ParseIntError),
} }
impl CompilerError { impl CompilerError {
@ -102,6 +104,7 @@ impl Display for CompilerError {
ParamList(params.clone()), ParamList(params.clone()),
pos pos
), ),
CompilerError::ParseIntError(err) => format!("Failed to parse integer value: {}", err),
}; };
write!(f, "{}", text) write!(f, "{}", text)
} }

View File

@ -20,14 +20,15 @@ fn main() {
eprintln!("Syntax error: {}", error); eprintln!("Syntax error: {}", error);
std::process::exit(1); std::process::exit(1);
} }
//dbg!(&parsed); dbg!(&parsed);
let print = BuiltinFunctionDef::new( let print = BuiltinFunctionDef::new(
"print", "print",
vec![VariableType::TypeString], vec![VariableType::TypeString],
Box::new(move |args| { Box::new(move |args| {
let Value::StringVal(string) = &args[0]; if let Value::StringVal(string) = &args[0] {
println!("{}", string); println!("{}", string);
}
}), }),
); );
let builtin_functions = BuiltinFunctions(vec![print]); let builtin_functions = BuiltinFunctions(vec![print]);
@ -39,7 +40,7 @@ fn main() {
eprintln!("Compilation error: {}", error); eprintln!("Compilation error: {}", error);
std::process::exit(1); std::process::exit(1);
} }
//dbg!(&compiled); dbg!(&compiled);
let mut vm = VirtualMachine::from(compiled.unwrap()); let mut vm = VirtualMachine::from(compiled.unwrap());
vm.add_builtin_functions(builtin_functions); vm.add_builtin_functions(builtin_functions);

View File

@ -13,6 +13,7 @@ const ALLOWED_IDENT_BEGIN_CHARS: [char; 26] = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', 't', 'u', 'v', 'w', 'x', 'y', 'z',
]; ];
const ALLOWED_NUMERALS: [char; 10] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
pub struct Parser { pub struct Parser {
text: Vec<char>, text: Vec<char>,
@ -173,6 +174,33 @@ impl Parser {
} }
} }
pub fn expect_numeral_lit(&mut self) -> Expect {
self.skip_whitespace();
let mut content: Option<String> = None;
while {
if let Some(peek) = self.peek(self.inconfidence) {
if ALLOWED_NUMERALS.contains(&peek) {
let mut string = match content {
Some(s) => s,
None => String::new(),
};
string.push(peek);
content = Some(string);
self.inconfidence += 1;
true
} else {
false
}
} else {
false
}
} {}
Expect {
text: content,
parser: self,
}
}
pub fn advance_cursor(&mut self) { pub fn advance_cursor(&mut self) {
let curr = self.peek(0).unwrap(); let curr = self.peek(0).unwrap();
self.cursor += 1; self.cursor += 1;

View File

@ -122,6 +122,11 @@ impl Pattern {
pos, pos,
LiteralPattern::StringLit(string), LiteralPattern::StringLit(string),
)) ))
} else if let Some(int) = parser.expect_numeral_lit().get() {
Ok(Pattern::LiteralPattern(
pos,
LiteralPattern::Integer32Lit(int),
))
} else if let Some(ident) = parser.expect_ident().get() { } else if let Some(ident) = parser.expect_ident().get() {
Ok(Pattern::IdentPattern(pos, ident)) Ok(Pattern::IdentPattern(pos, ident))
} else { } else {
@ -133,4 +138,5 @@ impl Pattern {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum LiteralPattern { pub enum LiteralPattern {
StringLit(String), StringLit(String),
Integer32Lit(String),
} }

View File

@ -149,6 +149,14 @@ impl VirtualMachine {
Err(RuntimePanic::StackOverflow) Err(RuntimePanic::StackOverflow)
} }
} }
Command::I32Lit(val) => {
if self.stack.len() < usize::MAX {
self.stack.push(Value::I32Val(val));
Ok(())
} else {
Err(RuntimePanic::StackOverflow)
}
}
Command::FunctionCall(funcid) => { Command::FunctionCall(funcid) => {
if self.functions.len() <= funcid { if self.functions.len() <= funcid {
Err(RuntimePanic::InvalidFuncAddress) Err(RuntimePanic::InvalidFuncAddress)
@ -194,12 +202,14 @@ impl AllocatedVar {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value { pub enum Value {
StringVal(String), StringVal(String),
I32Val(i32),
} }
impl Value { impl Value {
fn get_type(&self) -> VariableType { fn get_type(&self) -> VariableType {
match self { match self {
Value::StringVal(_) => VariableType::TypeString, Value::StringVal(_) => VariableType::TypeString,
Value::I32Val(_) => VariableType::TypeI32,
} }
} }
} }
@ -207,12 +217,14 @@ impl Value {
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum VariableType { pub enum VariableType {
TypeString, TypeString,
TypeI32,
} }
impl ToString for VariableType { impl ToString for VariableType {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
VariableType::TypeString => "String".to_string(), VariableType::TypeString => "String".to_string(),
VariableType::TypeI32 => "i32".to_string(),
} }
} }
} }