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 dotus = otus;
print(dotus);
let gotus = 3;

View File

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::num::ParseIntError;
use super::errors::CompilerError;
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
VarToReg(HeapID, RegID), // Bring Variable to registery at RegID
StringLit(String), // Bring String Literal to Stack
I32Lit(i32), // Bring i32 Literal to Stack
FunctionCall(FuncID), // Call Function at FuncID
}
@ -145,9 +147,24 @@ impl Compiler {
fn handle_literal(&mut self, pattern: LiteralPattern) -> Result<VariableType, CompilerError> {
match pattern {
LiteralPattern::StringLit(string) => self.list.push(Command::StringLit(string)),
LiteralPattern::StringLit(string) => {
self.list.push(Command::StringLit(string));
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)),
}
Ok(VariableType::TypeString)
}
}

View File

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

View File

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

View File

@ -122,6 +122,11 @@ impl Pattern {
pos,
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() {
Ok(Pattern::IdentPattern(pos, ident))
} else {
@ -133,4 +138,5 @@ impl Pattern {
#[derive(Debug, Clone)]
pub enum LiteralPattern {
StringLit(String),
Integer32Lit(String),
}

View File

@ -149,6 +149,14 @@ impl VirtualMachine {
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) => {
if self.functions.len() <= funcid {
Err(RuntimePanic::InvalidFuncAddress)
@ -194,12 +202,14 @@ impl AllocatedVar {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value {
StringVal(String),
I32Val(i32),
}
impl Value {
fn get_type(&self) -> VariableType {
match self {
Value::StringVal(_) => VariableType::TypeString,
Value::I32Val(_) => VariableType::TypeI32,
}
}
}
@ -207,12 +217,14 @@ impl Value {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum VariableType {
TypeString,
TypeI32,
}
impl ToString for VariableType {
fn to_string(&self) -> String {
match self {
VariableType::TypeString => "String".to_string(),
VariableType::TypeI32 => "i32".to_string(),
}
}
}