mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-13 18:10:42 +01:00
Fixed function re-definitions sometimes being parsed as calls
This commit is contained in:
parent
23edc83577
commit
7154d38eb3
@ -31,6 +31,7 @@ pub struct Context {
|
|||||||
/// whenever a unit in the expression is found. Eg. unit a = 3b, it will be set to Some("b")
|
/// whenever a unit in the expression is found. Eg. unit a = 3b, it will be set to Some("b")
|
||||||
unit_decl_base_unit: Option<String>,
|
unit_decl_base_unit: Option<String>,
|
||||||
other_radix: Option<u8>,
|
other_radix: Option<u8>,
|
||||||
|
current_stmt_start_pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
@ -46,6 +47,7 @@ impl Context {
|
|||||||
parsing_unit_decl: false,
|
parsing_unit_decl: false,
|
||||||
unit_decl_base_unit: None,
|
unit_decl_base_unit: None,
|
||||||
other_radix: None,
|
other_radix: None,
|
||||||
|
current_stmt_start_pos: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
parse(&mut context, crate::prelude::INIT).unwrap();
|
parse(&mut context, crate::prelude::INIT).unwrap();
|
||||||
@ -127,6 +129,7 @@ pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, KalkError>
|
|||||||
|
|
||||||
let mut statements: Vec<Stmt> = Vec::new();
|
let mut statements: Vec<Stmt> = Vec::new();
|
||||||
while !is_at_end(context) {
|
while !is_at_end(context) {
|
||||||
|
context.current_stmt_start_pos = context.pos;
|
||||||
let parsed = match parse_stmt(context) {
|
let parsed = match parse_stmt(context) {
|
||||||
Ok(stmt) => stmt,
|
Ok(stmt) => stmt,
|
||||||
Err(KalkError::WasStmt(stmt)) => stmt,
|
Err(KalkError::WasStmt(stmt)) => stmt,
|
||||||
@ -294,6 +297,7 @@ fn parse_and(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_comparison(context: &mut Context) -> Result<Expr, KalkError> {
|
fn parse_comparison(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
|
let at_start_of_line = context.current_stmt_start_pos == context.pos;
|
||||||
let mut left = parse_to(context)?;
|
let mut left = parse_to(context)?;
|
||||||
|
|
||||||
// Equality check
|
// Equality check
|
||||||
@ -306,7 +310,9 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
{
|
{
|
||||||
let op = advance(context).kind;
|
let op = advance(context).kind;
|
||||||
|
|
||||||
if let Some((identifier, parameters)) = analysis::is_fn_decl(&left) {
|
if let (true, Some((identifier, parameters))) =
|
||||||
|
(at_start_of_line, analysis::is_fn_decl(&left))
|
||||||
|
{
|
||||||
context.symbol_table.get_mut().set(Stmt::FnDecl(
|
context.symbol_table.get_mut().set(Stmt::FnDecl(
|
||||||
identifier.clone(),
|
identifier.clone(),
|
||||||
parameters.clone(),
|
parameters.clone(),
|
||||||
@ -595,6 +601,7 @@ fn parse_vector(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
||||||
|
let at_start_of_line = context.current_stmt_start_pos == context.pos;
|
||||||
let identifier = Identifier::from_full_name(&advance(context).value);
|
let identifier = Identifier::from_full_name(&advance(context).value);
|
||||||
|
|
||||||
let mut log_base = None;
|
let mut log_base = None;
|
||||||
@ -620,6 +627,8 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
.get_mut()
|
.get_mut()
|
||||||
.contains_fn(&identifier.pure_name)
|
.contains_fn(&identifier.pure_name)
|
||||||
{
|
{
|
||||||
|
let identifier_pos = context.pos;
|
||||||
|
|
||||||
// Function call
|
// Function call
|
||||||
let mut arguments = match parse_primary(context)? {
|
let mut arguments = match parse_primary(context)? {
|
||||||
Expr::Vector(arguments) => arguments,
|
Expr::Vector(arguments) => arguments,
|
||||||
@ -627,6 +636,35 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, KalkError> {
|
|||||||
argument => vec![argument],
|
argument => vec![argument],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If it's a re-definition, revert and parse as a declaration
|
||||||
|
if at_start_of_line
|
||||||
|
&& match_token(context, TokenKind::Equals)
|
||||||
|
&& arguments.iter().all(|x| matches!(x, Expr::Var(_)))
|
||||||
|
{
|
||||||
|
for argument in &arguments {
|
||||||
|
let mut all_vars_exist = true;
|
||||||
|
if let Expr::Var(argument_identifier) = argument {
|
||||||
|
if !context
|
||||||
|
.symbol_table
|
||||||
|
.get_mut()
|
||||||
|
.contains_var(&argument_identifier.full_name)
|
||||||
|
{
|
||||||
|
all_vars_exist = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !all_vars_exist {
|
||||||
|
context
|
||||||
|
.symbol_table
|
||||||
|
.get_mut()
|
||||||
|
.get_and_remove_fn(&identifier.full_name);
|
||||||
|
context.pos = identifier_pos;
|
||||||
|
|
||||||
|
return Ok(Expr::Var(identifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(log_base) = log_base {
|
if let Some(log_base) = log_base {
|
||||||
let log_arg = arguments.remove(0);
|
let log_arg = arguments.remove(0);
|
||||||
Ok(Expr::FnCall(
|
Ok(Expr::FnCall(
|
||||||
|
@ -81,6 +81,10 @@ impl SymbolTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_and_remove_fn(&mut self, identifier: &str) -> Option<Stmt> {
|
||||||
|
self.hashmap.remove(&format!("fn.{}", identifier))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_and_remove_var(&mut self, identifier: &str) -> Option<Stmt> {
|
pub fn get_and_remove_var(&mut self, identifier: &str) -> Option<Stmt> {
|
||||||
self.hashmap.remove(&format!("var.{}", identifier))
|
self.hashmap.remove(&format!("var.{}", identifier))
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
x = 2
|
x = 2
|
||||||
x = 3
|
x = 3
|
||||||
f(x) = 2x
|
f(x, y, z) = x * y = z
|
||||||
f(x) = 3x
|
f(x, 2, 6)
|
||||||
|
f(x, y, z) = 2 * x * y = z
|
||||||
|
|
||||||
f(2) = 6 and x = 3
|
f(2, 3, 12) and x = 3
|
Loading…
Reference in New Issue
Block a user