[fine] Starting on pattern matching, make patterns explicit
This commit is contained in:
parent
f00b9e22e7
commit
deed9d9a45
4 changed files with 178 additions and 50 deletions
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
parser::{SyntaxTree, Tree, TreeKind, TreeRef},
|
||||
parser::{Child, SyntaxTree, Tree, TreeKind, TreeRef},
|
||||
semantics::{Declaration, Location, Semantics, Type},
|
||||
tokens::TokenKind,
|
||||
};
|
||||
|
|
@ -298,7 +298,7 @@ fn compile_expression(c: &mut Compiler, t: TreeRef) {
|
|||
TreeKind::FieldValue => compile_field_value(c, t, tree),
|
||||
TreeKind::GroupingExpression => compile_grouping(c, tree),
|
||||
TreeKind::Identifier => compile_identifier_expression(c, t, tree),
|
||||
TreeKind::IsExpression => compile_is_expression(c, t, tree),
|
||||
TreeKind::IsExpression => compile_is_expression(c, tree),
|
||||
TreeKind::LiteralExpression => compile_literal(c, t, tree),
|
||||
TreeKind::MemberAccess => compile_member_access(c, tree),
|
||||
TreeKind::NewObjectExpression => compile_new_object_expression(c, t, tree),
|
||||
|
|
@ -620,50 +620,56 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
|
|||
OK
|
||||
}
|
||||
|
||||
fn compile_is_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> Option<()> {
|
||||
fn compile_is_expression(c: &mut Compiler, tree: &Tree) -> Option<()> {
|
||||
compile_expression(c, tree.nth_tree(0)?);
|
||||
|
||||
compile_pattern(c, tree.nth_tree(2)?)
|
||||
}
|
||||
|
||||
fn compile_pattern(c: &mut Compiler, t: TreeRef) -> Option<()> {
|
||||
let tree = &c.syntax[t];
|
||||
|
||||
// If you have a binding, dup and store now, it is in scope.
|
||||
let type_expr =
|
||||
if let Some(binding) = tree.child_tree_of_kind(c.syntax, TreeKind::VariableBinding) {
|
||||
if let Some(variable) = binding.nth_token(0) {
|
||||
let environment = c.semantics.environment_of(t);
|
||||
let declaration = environment.bind(variable)?;
|
||||
if let Some(binding) = tree.child_tree_of_kind(c.syntax, TreeKind::VariableBinding) {
|
||||
if let Some(variable) = binding.nth_token(0) {
|
||||
let environment = c.semantics.environment_of(t);
|
||||
let declaration = environment.bind(variable)?;
|
||||
|
||||
let Declaration::Variable {
|
||||
location: Location::Local,
|
||||
index,
|
||||
..
|
||||
} = declaration
|
||||
else {
|
||||
ice!(c, t, "is cannot make a non-local, non-variable declaration")
|
||||
};
|
||||
let Declaration::Variable {
|
||||
location: Location::Local,
|
||||
index,
|
||||
..
|
||||
} = declaration
|
||||
else {
|
||||
ice!(c, t, "is cannot make a non-local, non-variable declaration")
|
||||
};
|
||||
|
||||
c.push(Instruction::Dup);
|
||||
c.push(Instruction::StoreLocal(*index));
|
||||
}
|
||||
|
||||
binding.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?
|
||||
} else {
|
||||
tree.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?
|
||||
};
|
||||
|
||||
compile_type_expr_eq(c, type_expr.nth_tree(0)?);
|
||||
|
||||
if let Some(tok) = tree.nth_token(3) {
|
||||
if tok.kind == TokenKind::And {
|
||||
let jump_true_index = c.push(Instruction::JumpTrue(0));
|
||||
|
||||
c.push(Instruction::PushFalse);
|
||||
let jump_end_index = c.push(Instruction::Jump(0));
|
||||
|
||||
c.patch(jump_true_index, |i| Instruction::JumpTrue(i));
|
||||
|
||||
compile_expression(c, tree.nth_tree(4)?);
|
||||
c.patch(jump_end_index, |i| Instruction::Jump(i));
|
||||
c.push(Instruction::Dup);
|
||||
c.push(Instruction::StoreLocal(*index));
|
||||
}
|
||||
}
|
||||
|
||||
let type_expr = tree.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?;
|
||||
compile_type_expr_eq(c, type_expr.nth_tree(0)?);
|
||||
|
||||
let and_index = tree.children.iter().position(|c| match c {
|
||||
Child::Token(t) => t.kind == TokenKind::And,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
if let Some(and_index) = and_index {
|
||||
// This is the tail end of an "AND" expression.
|
||||
let jump_true_index = c.push(Instruction::JumpTrue(0));
|
||||
|
||||
c.push(Instruction::PushFalse);
|
||||
let jump_end_index = c.push(Instruction::Jump(0));
|
||||
|
||||
c.patch(jump_true_index, |i| Instruction::JumpTrue(i));
|
||||
|
||||
compile_expression(c, tree.nth_tree(and_index + 1)?);
|
||||
c.patch(jump_end_index, |i| Instruction::Jump(i));
|
||||
};
|
||||
|
||||
OK
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue