Skip to content

Commit

Permalink
very minor restructuring of function order
Browse files Browse the repository at this point in the history
  • Loading branch information
dannyvankooten committed Nov 26, 2022
1 parent 60a74c8 commit c050d62
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 115 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ criterion = {version = "0.3", default-features = false }

[profile.bench]
lto = true
debug = true

[profile.release]
debug = true
lto = true

# Criterion benchmarks:
[[bench]]
Expand Down
2 changes: 1 addition & 1 deletion src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ impl Object {
}

/// Create a new function value
#[inline]
pub fn function(ip: u32, num_locals: u16) -> Self {
let value = ((ip as isize) << 16) | num_locals as isize;
Self::with_type((value << VALUE_SHIFT_BITS) as _, Type::Function)
Expand Down Expand Up @@ -564,6 +563,7 @@ impl Display for Type {
}

/// Allocate a chunk of memory with the given layout
#[inline]
fn allocate(layout: Layout) -> *mut u8 {
// Safety: we only call this function for types with a non-zero layout
let ptr = unsafe { alloc(layout) };
Expand Down
201 changes: 100 additions & 101 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,110 @@ impl<'a> Parser<'a> {
self.current_token = self.tokenizer.next().unwrap_or(Token::Illegal);
}

/// Assert current token is of the given type and skips it
#[inline]
fn skip(&mut self, t: Token) -> Result<(), ParseError> {
if self.current_token != t {
return Err(ParseError::SyntaxError(format!(
"onverwachte token. verwacchte {t:?}, maar kreeg {:?}",
self.current_token
)));
}
self.advance();
Ok(())
}

/// Skips the current token if it is of the given type
#[inline]
fn skip_optional(&mut self, t: Token) {
if self.current_token == t {
self.advance()
}
}

/// Parses an operator token
fn parse_operator(&mut self) -> Operator {
Operator::from(self.current_token)
}

/// Parse an expression
#[inline]
fn parse_expr(&mut self, precedence: Precedence) -> Result<Expr, ParseError> {
let mut left = match self.current_token {
Token::Int(s) => self.parse_int_expression(s),
Token::Float(s) => self.parse_float_expression(s),
Token::True => self.parse_bool_expression(true),
Token::False => self.parse_bool_expression(false),
Token::String(s) => self.parse_string_expression(s),
Token::OpenParen => {
self.advance();
let expr = self.parse_expr(Precedence::Lowest)?;
self.skip(Token::CloseParen)?;
expr
}
Token::If => self.parse_if_expr()?,
Token::Bang | Token::Minus => self.parse_prefix_expr()?,
Token::Identifier(name) => self.parse_ident(name),
Token::Func => self.parse_function_expr()?,
Token::While => self.parse_while_expr()?,
Token::OpenBracket => self.parse_array_expr()?,
_ => {
return Err(ParseError::SyntaxError(format!(
"onverwachte token. verwachtte een expressie, maar kreeg {:?}",
self.current_token
)))
}
};

// keep going
while self.current_token != Token::Semi && precedence < self.current_token.precedence() {
left = match self.current_token {
Token::Lt
| Token::Lte
| Token::Gt
| Token::Gte
| Token::Eq
| Token::Neq
| Token::Plus
| Token::Minus
| Token::Slash
| Token::Star
| Token::And
| Token::Or
| Token::Percent => self.parse_infix_expr(left)?,
Token::Assign => self.parse_assign_expr(left)?,
Token::OpenParen => self.parse_call_expr(left)?,
Token::OpenBracket => self.parse_index_expr(left)?,
_ => return Ok(left),
};
}

Ok(left)
}

/// Parse a single statement
#[inline]
fn parse_statement(&mut self) -> Result<Stmt, ParseError> {
let stmt = match self.current_token {
Token::Declare => self.parse_decl_statement()?,
Token::OpenBrace => Stmt::Block(self.parse_block_statement()?),
Token::Return => self.parse_return_statement()?,
Token::Continue => {
self.advance();
Stmt::Continue
}
Token::Break => {
self.advance();
Stmt::Break
}
_ => Stmt::Expr(self.parse_expr(Precedence::Lowest)?),
};

self.skip_optional(Token::Semi);

Ok(stmt)
}

/// Parses OpAssign expressions, like a += 5
/// This is just syntactic sugar, internally they are replaced by two seperate expression
/// Perhaps this deserves its own specialized OpCode in the future to save some instructions
Expand Down Expand Up @@ -170,27 +269,6 @@ impl<'a> Parser<'a> {
})
}

/// Assert current token is of the given type and skips it
#[inline]
fn skip(&mut self, t: Token) -> Result<(), ParseError> {
if self.current_token != t {
return Err(ParseError::SyntaxError(format!(
"onverwachte token. verwacchte {t:?}, maar kreeg {:?}",
self.current_token
)));
}
self.advance();
Ok(())
}

/// Skips the current token if it is of the given type
#[inline]
fn skip_optional(&mut self, t: Token) {
if self.current_token == t {
self.advance()
}
}

#[inline]
fn parse_int_expression(&mut self, strval: &str) -> Expr {
self.advance();
Expand Down Expand Up @@ -272,7 +350,6 @@ impl<'a> Parser<'a> {
})
}

#[inline]
fn parse_ident(&mut self, name: &str) -> Expr {
let expr = Expr::Identifier(name.to_owned());
self.advance();
Expand Down Expand Up @@ -355,61 +432,6 @@ impl<'a> Parser<'a> {
})
}

/// Parse an expression
#[inline]
fn parse_expr(&mut self, precedence: Precedence) -> Result<Expr, ParseError> {
let mut left = match self.current_token {
Token::Int(s) => self.parse_int_expression(s),
Token::Float(s) => self.parse_float_expression(s),
Token::True => self.parse_bool_expression(true),
Token::False => self.parse_bool_expression(false),
Token::String(s) => self.parse_string_expression(s),
Token::OpenParen => {
self.advance();
let expr = self.parse_expr(Precedence::Lowest)?;
self.skip(Token::CloseParen)?;
expr
}
Token::If => self.parse_if_expr()?,
Token::Bang | Token::Minus => self.parse_prefix_expr()?,
Token::Identifier(name) => self.parse_ident(name),
Token::Func => self.parse_function_expr()?,
Token::While => self.parse_while_expr()?,
Token::OpenBracket => self.parse_array_expr()?,
_ => {
return Err(ParseError::SyntaxError(format!(
"onverwachte token. verwachtte een expressie, maar kreeg {:?}",
self.current_token
)))
}
};

// keep going
while self.current_token != Token::Semi && precedence < self.current_token.precedence() {
left = match self.current_token {
Token::Lt
| Token::Lte
| Token::Gt
| Token::Gte
| Token::Eq
| Token::Neq
| Token::Plus
| Token::Minus
| Token::Slash
| Token::Star
| Token::And
| Token::Or
| Token::Percent => self.parse_infix_expr(left)?,
Token::Assign => self.parse_assign_expr(left)?,
Token::OpenParen => self.parse_call_expr(left)?,
Token::OpenBracket => self.parse_index_expr(left)?,
_ => return Ok(left),
};
}

Ok(left)
}

fn parse_decl_statement(&mut self) -> Result<Stmt, ParseError> {
// skip Token::Declare
self.advance();
Expand Down Expand Up @@ -440,29 +462,6 @@ impl<'a> Parser<'a> {
Ok(Stmt::Return(expr))
}

/// Parse a single statement
#[inline]
fn parse_statement(&mut self) -> Result<Stmt, ParseError> {
let stmt = match self.current_token {
Token::Declare => self.parse_decl_statement()?,
Token::OpenBrace => Stmt::Block(self.parse_block_statement()?),
Token::Return => self.parse_return_statement()?,
Token::Continue => {
self.advance();
Stmt::Continue
}
Token::Break => {
self.advance();
Stmt::Break
}
_ => Stmt::Expr(self.parse_expr(Precedence::Lowest)?),
};

self.skip_optional(Token::Semi);

Ok(stmt)
}

/// Parse a block (surrounded by curly braces)
/// Can be an unnamed block, function body, if consequence, etc.
fn parse_block_statement(&mut self) -> Result<BlockStmt, ParseError> {
Expand All @@ -481,7 +480,7 @@ impl<'a> Parser<'a> {
/// Parses the program string into an AST representation
pub fn parse(program: &str) -> Result<BlockStmt, ParseError> {
let mut parser = Parser::new(program);
let mut block = BlockStmt::with_capacity(64);
let mut block = BlockStmt::new();

while parser.current_token != Token::Illegal {
block.push(parser.parse_statement()?);
Expand Down
7 changes: 1 addition & 6 deletions src/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl Context {
}

/// Resolves a symbol in this context along with its absolute index (relative to the context its top scope)
#[inline]
fn resolve(&self, name: &str) -> Option<Symbol> {
let mut abs_index = self.total_len();
for scope in self.symbols.iter().rev() {
Expand All @@ -83,40 +84,34 @@ impl SymbolTable {
}

/// Returns a mutable reference to the current context
#[inline(always)]
fn current_context(&mut self) -> &mut Context {
self.contexts.last_mut().unwrap()
}

/// Create a new context to define symbols in.
/// This will always be a local context (as there is only one global context).
#[inline]
pub fn new_context(&mut self) {
self.contexts.push(Context::new(Scope::Local));
}

/// Destroys the current context and returns the maximum number of symbols it had at some point in time.
#[inline]
pub fn leave_context(&mut self) -> usize {
self.contexts.pop().unwrap().max_size()
}

/// Enter a new scope in the current context
/// For example, at the start of a block statement.
#[inline]
pub fn enter_scope(&mut self) {
self.current_context().symbols.push(Vec::new());
}

/// Leave scope in the current context.
/// For example, at the end of a block statement.
#[inline]
pub fn leave_scope(&mut self) {
self.current_context().symbols.pop().unwrap();
}

/// Define a symbol in the current context (and current scope within that context).
#[inline]
pub fn define(&mut self, name: &str) -> Symbol {
self.current_context().define(name)
}
Expand Down
11 changes: 5 additions & 6 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl VM {
}

/// Sets the instruction pointer to the given value
#[inline]
#[inline(always)]
fn jump(&mut self, ip: u16) {
self.ip = ip as usize;
}
Expand Down Expand Up @@ -286,13 +286,12 @@ impl VM {
}
OpCode::JumpIfFalse => {
let condition = self.pop();
let evaluation = match condition.tag() {
Type::Bool => Ok(condition.as_bool()),
_ => Err(Error::TypeError(format!("kan object met type {} niet gebruiken als voorwaarde. Gebruik evt. bool() om te type casten naar boolean.", condition.tag()))),
}?;
if condition.tag() != Type::Bool {
return Err(Error::TypeError(format!("kan object met type {} niet gebruiken als voorwaarde. Gebruik evt. bool() om te type casten naar boolean.", condition.tag())));
}

let pos = self.read_u16();
if !evaluation {
if !condition.as_bool() {
self.jump(pos);
}
}
Expand Down

0 comments on commit c050d62

Please sign in to comment.