Skip to content

Commit

Permalink
Fix segfault for op::INVOKE
Browse files Browse the repository at this point in the history
  • Loading branch information
ajeetdsouza committed May 11, 2024
1 parent 431f59d commit 6e22616
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 31 deletions.
11 changes: 6 additions & 5 deletions src/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use anyhow::{Context, Result};
use nu_ansi_term::{Color, Style};
use reedline::{
EditCommand, Emacs, FileBackedHistory, KeyCode, KeyModifiers, PromptEditMode,
PromptHistorySearch, Reedline, ReedlineEvent, StyledText, ValidationResult,
PromptHistorySearch, Reedline, ReedlineEvent, Signal, StyledText, ValidationResult,
};
use tree_sitter_highlight::{self, HighlightConfiguration, HighlightEvent};
use tree_sitter_lox::{self, HIGHLIGHTS_QUERY};
Expand All @@ -25,13 +25,13 @@ pub fn run() -> Result<()> {
editor.sync_history().context("could not sync history file")?;

match line {
Ok(reedline::Signal::Success(line)) => {
Ok(Signal::Success(line)) => {
if let Err(errors) = vm.run(&line, stdout) {
crate::error::report_errors(stderr, &vm.source, &errors)
}
}
Ok(reedline::Signal::CtrlC) => eprintln!("^C"),
Ok(reedline::Signal::CtrlD) => break,
Ok(Signal::CtrlC) => eprintln!("^C"),
Ok(Signal::CtrlD) => break,
Err(e) => {
eprintln!("error: {e:?}");
break;
Expand Down Expand Up @@ -129,7 +129,8 @@ impl reedline::Highlighter for Highlighter {
let mut output = StyledText::new();

let mut highlighter = tree_sitter_highlight::Highlighter::new();
let Ok(highlights) = highlighter.highlight(&self.config, line.as_bytes(), None, |_| None) else {
let Ok(highlights) = highlighter.highlight(&self.config, line.as_bytes(), None, |_| None)
else {
let style = Style::new().fg(PALETTE[0].fg);
output.push((style, line.to_string()));
return output;
Expand Down
79 changes: 53 additions & 26 deletions src/vm/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct Compiler {
impl Compiler {
/// Creates a compiler for a new script.
pub fn new(gc: &mut Gc) -> Self {
let name = gc.alloc("");
let name = gc.alloc("<script>");
Self {
ctx: CompilerCtx {
function: gc.alloc(ObjectFunction::new(name, 0)),
Expand Down Expand Up @@ -347,18 +347,48 @@ impl Compiler {
.try_into()
.map_err(|_| (OverflowError::TooManyArgs.into(), span.clone()))?;

self.compile_expr(&call.callee, gc)?;
for arg in &call.args {
self.compile_expr(arg, gc)?;
}
match &call.callee.0 {
Expr::Get(get) => {
self.compile_expr(&get.object, gc)?;
for arg in &call.args {
self.compile_expr(arg, gc)?;
}

let ops = unsafe { &mut (*self.ctx.function).chunk.ops };
match ops.len().checked_sub(2) {
Some(idx) if ops[idx] == op::GET_PROPERTY => ops[idx] = op::INVOKE,
Some(idx) if ops[idx] == op::GET_SUPER => ops[idx] = op::SUPER_INVOKE,
Some(_) | None => self.emit_u8(op::CALL, span),
let name = gc.alloc(&get.name).into();
self.emit_u8(op::INVOKE, span);
self.emit_constant(name, span)?;
self.emit_u8(arg_count, span);
}
Expr::Super(super_) => match self.class_ctx.last() {
Some(class_ctx) if !class_ctx.has_super => {
return Err((SyntaxError::SuperWithoutSuperclass.into(), span.clone()));
}
Some(_) => {
self.get_variable("this", span, gc)?;
for arg in &call.args {
self.compile_expr(arg, gc)?;
}
self.get_variable("super", span, gc)?;

let name = gc.alloc(&super_.name).into();
self.emit_u8(op::SUPER_INVOKE, span);
self.emit_constant(name, span)?;
self.emit_u8(arg_count, span);
}
None => {
return Err((SyntaxError::SuperOutsideClass.into(), span.clone()));
}
},
_ => {
self.compile_expr(&call.callee, gc)?;
for arg in &call.args {
self.compile_expr(arg, gc)?;
}

self.emit_u8(op::CALL, span);
self.emit_u8(arg_count, span);
}
}
self.emit_u8(arg_count, span);
}
Expr::Get(get) => {
self.compile_expr(&get.object, gc)?;
Expand Down Expand Up @@ -472,22 +502,19 @@ impl Compiler {
self.emit_u8(op::SET_PROPERTY, span);
self.emit_constant(name, span)?;
}
Expr::Super(super_) => {
match self.class_ctx.last() {
Some(class_ctx) => {
if !class_ctx.has_super {
return Err((SyntaxError::SuperWithoutSuperclass.into(), span.clone()));
}
}
None => return Err((SyntaxError::SuperOutsideClass.into(), span.clone())),
Expr::Super(super_) => match self.class_ctx.last() {
Some(class_ctx) if !class_ctx.has_super => {
return Err((SyntaxError::SuperWithoutSuperclass.into(), span.clone()));
}

let name = gc.alloc(&super_.name).into();
self.get_variable("this", span, gc)?;
self.get_variable("super", span, gc)?;
self.emit_u8(op::GET_SUPER, span);
self.emit_constant(name, span)?;
}
Some(_) => {
let name = gc.alloc(&super_.name).into();
self.get_variable("this", span, gc)?;
self.get_variable("super", span, gc)?;
self.emit_u8(op::GET_SUPER, span);
self.emit_constant(name, span)?;
}
None => return Err((SyntaxError::SuperOutsideClass.into(), span.clone())),
},
Expr::Var(var) => self.get_variable(&var.var.name, span, gc)?,
}
Ok(())
Expand Down

0 comments on commit 6e22616

Please sign in to comment.