Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benches/src/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::time::Duration;
fn run_string(input: &str) -> Result<String, InterpreterError> {
let buf: Vec<u8> = vec![];
let mut interpreter = Interpreter::new(buf);
interpreter.run_str(std::hint::black_box(input), false)
interpreter.run_str(std::hint::black_box(input))
}

#[allow(unused)]
Expand Down
7 changes: 2 additions & 5 deletions ndc_bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ mod highlighter;
#[command(version = "0.2.0")]
#[command(about = "An interpreter for the Andy C++ language")]
struct Cli {
#[arg(long)]
debug: bool,

#[arg(short = 'C', long, default_value_t = 1)]
context_lines: usize,

Expand Down Expand Up @@ -122,7 +119,7 @@ fn main() -> anyhow::Result<()> {

let stdout = std::io::stdout();
let mut interpreter = Interpreter::new(stdout);
match into_miette_result(interpreter.run_str(&string, cli.debug)) {
match into_miette_result(interpreter.run_str(&string)) {
// we can just ignore successful runs because we have print statements
Ok(_final_value) => {}
Err(report) => {
Expand All @@ -147,7 +144,7 @@ fn main() -> anyhow::Result<()> {
}
Action::Docs(query) => return docs(query.as_deref()),
Action::StartRepl => {
repl::run(cli.debug)?;
repl::run()?;
}
Action::RunLsp => start_lsp(),
}
Expand Down
4 changes: 2 additions & 2 deletions ndc_bin/src/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl rustyline::highlight::Highlighter for RustlylineHelper {
}
}

pub fn run(debug: bool) -> anyhow::Result<()> {
pub fn run() -> anyhow::Result<()> {
let h = RustlylineHelper {};

let mut rl = Editor::new()?;
Expand All @@ -44,7 +44,7 @@ pub fn run(debug: bool) -> anyhow::Result<()> {
let _ = rl.add_history_entry(line.as_str());

// Run the line we just read through the interpreter
match into_miette_result(interpreter.run_str(line.as_str(), debug)) {
match into_miette_result(interpreter.run_str(line.as_str())) {
Ok(output) => {
if !output.is_empty() {
println!("{output}")
Expand Down
20 changes: 13 additions & 7 deletions ndc_lib/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,16 @@ pub enum Lvalue {
Identifier {
identifier: String,
resolved: Option<ResolvedVar>,
span: Span,
inferred_type: Option<StaticType>,
},
// Example: `foo()[1] = ...`
Index {
value: Box<ExpressionLocation>,
index: Box<ExpressionLocation>,
},
// Example: `let a, b = ...`
Sequence(Vec<Lvalue>),
Sequence(Vec<Self>),
}

impl Eq for Expression {}
Expand Down Expand Up @@ -240,19 +242,23 @@ impl Lvalue {
_ => false,
}
}

pub fn new_identifier(identifier: String, span: Span) -> Self {
Self::Identifier {
identifier,
resolved: None,
span,
inferred_type: None,
}
}
}

impl TryFrom<ExpressionLocation> for Lvalue {
type Error = ParseError;

fn try_from(value: ExpressionLocation) -> Result<Self, Self::Error> {
match value.expression {
Expression::Identifier {
name: identifier, ..
} => Ok(Self::Identifier {
identifier,
resolved: None,
}),
Expression::Identifier { name, .. } => Ok(Self::new_identifier(name, value.span)),
Expression::Index { value, index } => Ok(Self::Index { value, index }),
Expression::List { values } | Expression::Tuple { values } => Ok(Self::Sequence(
values
Expand Down
6 changes: 1 addition & 5 deletions ndc_lib/src/ast/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,11 +656,7 @@ impl Parser {
let identifier_span = l_value.span;
let first_argument_span = expr.span;
let identifier = Lvalue::try_from(l_value)?;
let Lvalue::Identifier {
identifier,
resolved: None,
} = identifier
else {
let Lvalue::Identifier { identifier, .. } = identifier else {
unreachable!("Guaranteed to match by previous call to require_identifier")
};

Expand Down
6 changes: 2 additions & 4 deletions ndc_lib/src/interpreter/evaluate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub(crate) fn evaluate_expression(
Lvalue::Identifier {
identifier,
resolved: resolved_l_value,
..
} => {
let resolved_l_value = resolved_l_value.expect("lvalue must be resolved");
let rhs = evaluate_expression(r_value, environment)?;
Expand Down Expand Up @@ -675,10 +676,7 @@ fn declare_or_assign_variable(
span: Span,
) -> EvaluationResult {
match l_value {
Lvalue::Identifier {
identifier: _,
resolved,
} => {
Lvalue::Identifier { resolved, .. } => {
environment
.borrow_mut()
.set(resolved.expect("must be resolved"), value.clone());
Expand Down
46 changes: 18 additions & 28 deletions ndc_lib/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub struct Interpreter {
analyser: Analyser,
}

#[allow(clippy::dbg_macro, clippy::print_stdout, clippy::print_stderr)]
impl Interpreter {
#[must_use]
pub fn new<T>(dest: T) -> Self
Expand All @@ -45,25 +44,25 @@ impl Interpreter {
self.environment
}

pub fn run_str(&mut self, input: &str, debug: bool) -> Result<String, InterpreterError> {
let scanner = Lexer::new(input);
let tokens = scanner.collect::<Result<Vec<TokenLocation>, _>>()?;

if debug {
for token in &tokens {
eprintln!("{token:?}");
}
}

let mut parser = crate::ast::Parser::from_tokens(tokens);
pub fn analyse_str(
&mut self,
input: &str,
) -> Result<Vec<ExpressionLocation>, InterpreterError> {
self.parse_and_analyse(input)
}

let mut expressions = parser.parse()?;
pub fn run_str(&mut self, input: &str) -> Result<String, InterpreterError> {
let expressions = self.parse_and_analyse(input)?;
let final_value = self.interpret(expressions.into_iter())?;
Ok(format!("{final_value}"))
}

if debug {
for s in &expressions {
println!("{s:#?}");
}
}
fn parse_and_analyse(
&mut self,
input: &str,
) -> Result<Vec<ExpressionLocation>, InterpreterError> {
let tokens = Lexer::new(input).collect::<Result<Vec<TokenLocation>, _>>()?;
let mut expressions = crate::ast::Parser::from_tokens(tokens).parse()?;

let checkpoint = self.analyser.checkpoint();
for e in &mut expressions {
Expand All @@ -73,16 +72,7 @@ impl Interpreter {
}
}

//dbg!(&expressions);
//dbg!(&self.analyser);

let final_value = self.interpret(expressions.into_iter())?;

if debug {
dbg!(&final_value, final_value.static_type());
}

Ok(format!("{final_value}"))
Ok(expressions)
}

fn interpret(
Expand Down
18 changes: 13 additions & 5 deletions ndc_lib/src/interpreter/semantic/analyser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ impl Analyser {
resolved_name,
parameters,
body,
return_type: return_type_slot,
..
} => {
// TODO: figuring out the type signature of function declarations is the rest of the owl
Expand All @@ -127,15 +128,17 @@ impl Analyser {
self.scope_tree.new_scope();
let param_types = self.resolve_parameters_declarative(parameters)?;

// TODO: instead of just hardcoding the return type of every function to StaticType::Any
// we should somehow collect all the returns that were encountered while analysing
// the body and then figuring out the LUB.
let return_type = self.analyse(body)?;
self.scope_tree.destroy_scope();
*return_type_slot = Some(return_type);

let function_type = StaticType::Function {
parameters: Some(param_types.clone()),
return_type: Box::new(return_type),
return_type: Box::new(
return_type_slot
.clone()
.expect("must have a value at this point"),
),
};

if let Some(slot) = pre_slot {
Expand Down Expand Up @@ -403,6 +406,7 @@ impl Analyser {
Lvalue::Identifier {
identifier,
resolved,
..
} => {
let Some(target) = self.scope_tree.get_binding_any(identifier) else {
return Err(AnalysisError::identifier_not_previously_declared(
Expand Down Expand Up @@ -433,6 +437,7 @@ impl Analyser {
Lvalue::Identifier {
identifier,
resolved,
..
} => {
let Some(target) = self.scope_tree.get_binding_any(identifier) else {
return Err(AnalysisError::identifier_not_previously_declared(
Expand Down Expand Up @@ -508,11 +513,14 @@ impl Analyser {
Lvalue::Identifier {
identifier,
resolved,
inferred_type,
..
} => {
*resolved = Some(
self.scope_tree
.create_local_binding(identifier.clone(), typ),
.create_local_binding(identifier.clone(), typ.clone()),
);
*inferred_type = Some(typ);
}
Lvalue::Index { index, value } => {
self.analyse(index)?;
Expand Down
Loading