Add lists
This introduces: * new syntax for list literals, put comma-separated values between braces for your new list * new syntax for indexing, do `foo[index]` to get the value in `foo` at `index`. Lists also allow negative indices too. Any type that wants to be indexed can include their own __index__ function as well. * new VM instruction, BuildList. List literals were a lot easier to implement using this rather than creating a new list, creating a temporary stack value, and then duplicating + pushing to that temporary value over and over. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -106,6 +106,12 @@ impl ExprVisitor for LineNumber {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Result<()> {
|
||||
expr.expr.accept(self).unwrap();
|
||||
self.update_end(expr.rbracket.line);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_primary_expr(&mut self, expr: &PrimaryExpr) -> Result<()> {
|
||||
self.update_start(expr.token.line);
|
||||
self.update_end(expr.token.line);
|
||||
@@ -117,6 +123,12 @@ impl ExprVisitor for LineNumber {
|
||||
self.update_end(expr.rbrace.line);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_list_expr(&mut self, expr: &ListExpr) -> Result<()> {
|
||||
self.update_start(expr.lbracket.line);
|
||||
self.update_end(expr.rbracket.line);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn expr_line_number(expr: &dyn Expr) -> LineRange {
|
||||
@@ -238,6 +250,10 @@ impl ExprVisitor for LocalAssignCollector {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_index_expr(&mut self, _expr: &IndexExpr) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_primary_expr(&mut self, _expr: &PrimaryExpr) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -246,6 +262,11 @@ impl ExprVisitor for LocalAssignCollector {
|
||||
// don't visit function expr, we're only collecting local assigns
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_list_expr(&mut self, _expr: &ListExpr) -> Result<()> {
|
||||
// there shouldn't be any local assignments inside of a list expression
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -326,6 +347,12 @@ impl ExprVisitor for LocalNameCollector {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Result<()> {
|
||||
expr.expr.accept(self)?;
|
||||
expr.index.accept(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_primary_expr(&mut self, expr: &PrimaryExpr) -> Result<()> {
|
||||
if expr.token.kind == TokenKind::Name {
|
||||
self.names.insert(expr.token.text.to_string());
|
||||
@@ -337,6 +364,13 @@ impl ExprVisitor for LocalNameCollector {
|
||||
// don't visit function expr, we're only collecting local assigns
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_list_expr(&mut self, expr: &ListExpr) -> Result<()> {
|
||||
for expr in &expr.exprs {
|
||||
expr.accept(self)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -863,6 +897,15 @@ impl ExprVisitor for Compiler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Result<()> {
|
||||
self.compile_expr(&expr.expr)?;
|
||||
let constant_id = self.insert_constant(Str::create("__index__"))?;
|
||||
self.emit(expr_line_number(expr), Op::GetAttr(constant_id));
|
||||
self.compile_expr(&expr.index)?;
|
||||
self.emit(expr_line_number(expr), Op::Call(1));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_primary_expr(&mut self, expr: &PrimaryExpr) -> Result<()> {
|
||||
match expr.token.kind {
|
||||
TokenKind::Name => {
|
||||
@@ -990,4 +1033,16 @@ impl ExprVisitor for Compiler {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_list_expr(&mut self, expr: &ListExpr) -> Result<()> {
|
||||
let line = expr_line_number(expr);
|
||||
|
||||
for expr in &expr.exprs {
|
||||
self.compile_expr(expr)?;
|
||||
}
|
||||
|
||||
self.emit(line, Op::BuildList(expr.exprs.len() as ListLen));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user