statements almost done, iteration statements causing issues

This commit is contained in:
gluax 2022-05-03 17:33:46 -07:00
parent 4612602807
commit d39ee31933
4 changed files with 108 additions and 41 deletions

View File

@ -76,9 +76,7 @@ impl<'a, V: ExpressionVisitor<'a>> VisitorDirector<'a, V> {
pub fn visit_call(&mut self, input: &'a CallExpression) {
if let VisitResult::VisitChildren = self.visitor.visit_call(input) {
for expr in input.arguments.iter() {
self.visit_expression(expr);
}
input.arguments.iter().for_each(|expr| self.visit_expression(expr));
}
}
}
@ -137,8 +135,11 @@ impl<'a, V: ExpressionVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V>
pub fn visit_console(&mut self, input: &'a ConsoleStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_console(input) {
if let ConsoleFunction::Assert(expr) = &input.function {
self.visit_expression(expr);
match &input.function {
ConsoleFunction::Assert(expr) => self.visit_expression(expr),
ConsoleFunction::Error(fmt) | ConsoleFunction::Log(fmt) => {
fmt.parameters.iter().for_each(|expr| self.visit_expression(expr));
}
}
}
}
@ -151,9 +152,7 @@ impl<'a, V: ExpressionVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V>
pub fn visit_block(&mut self, input: &'a Block) {
if let VisitResult::VisitChildren = self.visitor.visit_block(input) {
for stmt in input.statements.iter() {
self.visit_statement(stmt);
}
input.statements.iter().for_each(|stmt| self.visit_statement(stmt));
}
}
}
@ -161,9 +160,10 @@ impl<'a, V: ExpressionVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V>
impl<'a, V: ExpressionVisitor<'a> + ProgramVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V> {
pub fn visit_program(&mut self, input: &'a Program) {
if let VisitResult::VisitChildren = self.visitor.visit_program(input) {
for function in input.functions.values() {
self.visit_function(function);
}
input
.functions
.values()
.for_each(|function| self.visit_function(function));
}
}

View File

@ -77,6 +77,21 @@ impl<'a> SymbolTable<'a> {
pub fn lookup_var(&self, symbol: &Symbol) -> Option<&&'a DefinitionStatement> {
self.variables.variables.get(symbol)
}
pub fn push_variable_scope(&mut self) {
let current_scope = self.variables.clone();
self.variables = VariableSymbol {
parent: Some(Box::new(current_scope)),
inputs: Default::default(),
variables: Default::default(),
};
}
pub fn pop_variable_scope(&mut self) {
let parent = self.variables.parent.clone().unwrap();
self.variables = *parent;
}
}
impl<'a> Display for SymbolTable<'a> {

View File

@ -34,6 +34,17 @@ impl<'a> TypeChecker<'a> {
self.handler.emit_err(err1);
self.handler.emit_err(err2);
}
// Types match
_ => {}
}
}
fn assert_type(&self, type_: Result<Option<Type>>, expected: Type, span: &Span) {
match type_ {
Ok(Some(type_)) if type_ != expected => self
.handler
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into()),
// Types match
_ => {}
}
}
@ -103,27 +114,58 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
_ => {}
}
Default::default()
VisitResult::VisitChildren
}
fn visit_conditional(&mut self, _input: &'a ConditionalStatement) -> VisitResult {
Default::default()
fn visit_conditional(&mut self, input: &'a ConditionalStatement) -> VisitResult {
self.assert_type(input.condition.get_type(), Type::Boolean, input.span());
VisitResult::VisitChildren
}
fn visit_iteration(&mut self, _input: &'a IterationStatement) -> VisitResult {
Default::default()
fn visit_iteration(&mut self, input: &'a IterationStatement) -> VisitResult {
// TODO: need to change symbol table to some other repr for variables.
// self.symbol_table.insert_variable(input.variable.name, input);
let iter_var_type = input.get_type();
self.compare_types(iter_var_type.clone(), input.start.get_type(), input.span());
self.compare_types(iter_var_type, input.stop.get_type(), input.span());
VisitResult::VisitChildren
}
fn visit_console(&mut self, _input: &'a ConsoleStatement) -> VisitResult {
Default::default()
fn visit_console(&mut self, input: &'a ConsoleStatement) -> VisitResult {
match &input.function {
ConsoleFunction::Assert(expr) => {
self.assert_type(expr.get_type(), Type::Boolean, expr.span());
}
ConsoleFunction::Error(_) | ConsoleFunction::Log(_) => {
todo!("need to discuss this");
}
}
VisitResult::VisitChildren
}
fn visit_expression_statement(&mut self, _input: &'a ExpressionStatement) -> VisitResult {
Default::default()
}
fn visit_block(&mut self, input: &'a Block) -> VisitResult {
self.symbol_table.push_variable_scope();
// have to redo the logic here so we have scoping
input.statements.iter().for_each(|stmt| {
match stmt {
Statement::Return(stmt) => self.visit_return(stmt),
Statement::Definition(stmt) => self.visit_definition(stmt),
Statement::Assign(stmt) => self.visit_assign(stmt),
Statement::Conditional(stmt) => self.visit_conditional(stmt),
Statement::Iteration(stmt) => self.visit_iteration(stmt),
Statement::Console(stmt) => self.visit_console(stmt),
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
Statement::Block(stmt) => self.visit_block(stmt),
};
});
self.symbol_table.pop_variable_scope();
fn visit_block(&mut self, _input: &'a Block) -> VisitResult {
Default::default()
VisitResult::SkipChildren
}
}

View File

@ -53,23 +53,33 @@ create_messages!(
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
cannont_assign_to_const_input {
args: (input: impl Display),
msg: format!(
"Cannot assign to const input `{input}`",
),
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
cannont_assign_to_const_input {
args: (input: impl Display),
msg: format!(
"Cannot assign to const input `{input}`",
),
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
cannont_assign_to_const_var {
args: (var: impl Display),
msg: format!(
"Cannot assign to const variable `{var}`",
),
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
cannont_assign_to_const_var {
args: (var: impl Display),
msg: format!(
"Cannot assign to const variable `{var}`",
),
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
type_should_be {
args: (type_: impl Display, expected: impl Display),
msg: format!(
"Found type `{type_}` but type `{expected}` was expected",
),
help: None,
}
);