feat: execute source control flow and exact real arithmetic
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
use super::Spanned;
|
||||
use crate::Span;
|
||||
pub const AST_SCHEMA_ID: &str =
|
||||
"urn:endor:ast:sha256:c7c10c6a61158810fa55044f1aa79f3558ac18ca3be59cbf7f2499b5add8df5b";
|
||||
"urn:endor:ast:sha256:21b0349ac295d9bc8cedcad8f07d8e2d45cf220e19e7c2fad10269555fcfd71a";
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct AstDocument {
|
||||
@@ -141,6 +141,8 @@ pub enum StmtKind {
|
||||
Binding(Binding),
|
||||
Assignment(Assignment),
|
||||
MemberAssignment(MemberAssignment),
|
||||
If(IfStatement),
|
||||
While(WhileStatement),
|
||||
Return(ReturnStatement),
|
||||
Expression(Expr),
|
||||
Declaration(Decl),
|
||||
@@ -151,6 +153,8 @@ impl Spanned for StmtKind {
|
||||
Self::Binding(node) => node.span(),
|
||||
Self::Assignment(node) => node.span(),
|
||||
Self::MemberAssignment(node) => node.span(),
|
||||
Self::If(node) => node.span(),
|
||||
Self::While(node) => node.span(),
|
||||
Self::Return(node) => node.span(),
|
||||
Self::Expression(node) => node.span(),
|
||||
Self::Declaration(node) => node.span(),
|
||||
@@ -196,6 +200,31 @@ impl Spanned for MemberAssignment {
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct IfStatement {
|
||||
pub condition: Expr,
|
||||
pub body: Block,
|
||||
pub otherwise: Option<Block>,
|
||||
pub span: Span,
|
||||
}
|
||||
impl Spanned for IfStatement {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WhileStatement {
|
||||
pub condition: Expr,
|
||||
pub body: Block,
|
||||
pub span: Span,
|
||||
}
|
||||
impl Spanned for WhileStatement {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ReturnStatement {
|
||||
pub value: Option<Expr>,
|
||||
pub span: Span,
|
||||
@@ -263,4 +292,10 @@ pub enum BinaryOp {
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Equal,
|
||||
NotEqual,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
use super::{
|
||||
Assignment, AstDocument, AstRoot, BinaryOp, Binding, Block, Class, Decl, DeclKind, Expr,
|
||||
ExprKind, Function, InteractiveInput, MemberAssignment, Name, Parameter, Program,
|
||||
ReturnStatement, Spanned, Stmt, StmtKind, UnaryOp,
|
||||
ExprKind, Function, IfStatement, InteractiveInput, MemberAssignment, Name, Parameter, Program,
|
||||
ReturnStatement, Spanned, Stmt, StmtKind, UnaryOp, WhileStatement,
|
||||
};
|
||||
use crate::Span;
|
||||
pub trait Visitor {
|
||||
@@ -102,6 +102,18 @@ pub trait Visitor {
|
||||
self.leave_node();
|
||||
result
|
||||
}
|
||||
fn visit_if_statement(&mut self, node: &IfStatement) -> Result<(), Self::Error> {
|
||||
self.enter_node(node.span())?;
|
||||
let result = walk_if_statement(self, node);
|
||||
self.leave_node();
|
||||
result
|
||||
}
|
||||
fn visit_while_statement(&mut self, node: &WhileStatement) -> Result<(), Self::Error> {
|
||||
self.enter_node(node.span())?;
|
||||
let result = walk_while_statement(self, node);
|
||||
self.leave_node();
|
||||
result
|
||||
}
|
||||
fn visit_return_statement(&mut self, node: &ReturnStatement) -> Result<(), Self::Error> {
|
||||
self.enter_node(node.span())?;
|
||||
let result = walk_return_statement(self, node);
|
||||
@@ -243,6 +255,12 @@ pub fn walk_stmt_kind<V: Visitor + ?Sized>(
|
||||
StmtKind::MemberAssignment(value) => {
|
||||
visitor.visit_member_assignment(value)?;
|
||||
}
|
||||
StmtKind::If(value) => {
|
||||
visitor.visit_if_statement(value)?;
|
||||
}
|
||||
StmtKind::While(value) => {
|
||||
visitor.visit_while_statement(value)?;
|
||||
}
|
||||
StmtKind::Return(value) => {
|
||||
visitor.visit_return_statement(value)?;
|
||||
}
|
||||
@@ -280,6 +298,27 @@ pub fn walk_member_assignment<V: Visitor + ?Sized>(
|
||||
visitor.visit_span(&node.span)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn walk_if_statement<V: Visitor + ?Sized>(
|
||||
visitor: &mut V,
|
||||
node: &IfStatement,
|
||||
) -> Result<(), V::Error> {
|
||||
visitor.visit_expr(&node.condition)?;
|
||||
visitor.visit_block(&node.body)?;
|
||||
if let Some(value) = &node.otherwise {
|
||||
visitor.visit_block(value)?;
|
||||
}
|
||||
visitor.visit_span(&node.span)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn walk_while_statement<V: Visitor + ?Sized>(
|
||||
visitor: &mut V,
|
||||
node: &WhileStatement,
|
||||
) -> Result<(), V::Error> {
|
||||
visitor.visit_expr(&node.condition)?;
|
||||
visitor.visit_block(&node.body)?;
|
||||
visitor.visit_span(&node.span)?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn walk_return_statement<V: Visitor + ?Sized>(
|
||||
visitor: &mut V,
|
||||
node: &ReturnStatement,
|
||||
|
||||
@@ -78,6 +78,7 @@ peg::parser! {
|
||||
= declaration:declaration() {
|
||||
Stmt { span: declaration.span, kind: StmtKind::Declaration(declaration) }
|
||||
}
|
||||
/ control:control_statement() { control }
|
||||
/ binding:binding() { binding_statement(binding) }
|
||||
/ assignment:member_assignment() { assignment }
|
||||
/ assignment:assignment() { assignment }
|
||||
@@ -104,13 +105,25 @@ peg::parser! {
|
||||
}
|
||||
|
||||
rule local_statement() -> Stmt
|
||||
= binding:binding() { binding_statement(binding) }
|
||||
= control:control_statement() { control }
|
||||
/ binding:binding() { binding_statement(binding) }
|
||||
/ assignment:member_assignment() { assignment }
|
||||
/ assignment:assignment() { assignment }
|
||||
/ !return_keyword() expression:expression() {
|
||||
Stmt { span: expression.span, kind: StmtKind::Expression(expression) }
|
||||
}
|
||||
|
||||
rule control_statement() -> Stmt
|
||||
= start:keyword("if") condition:expression() body:block()
|
||||
otherwise:(keyword("else") body:block() { body })? {
|
||||
let span=start.through(otherwise.as_ref().map_or(body.span,|b|b.span));
|
||||
Stmt {span,kind:StmtKind::If(IfStatement {condition,body,otherwise,span})}
|
||||
}
|
||||
/ start:keyword("while") condition:expression() body:block() {
|
||||
let span=start.through(body.span);
|
||||
Stmt {span,kind:StmtKind::While(WhileStatement {condition,body,span})}
|
||||
}
|
||||
|
||||
rule assignment() -> Stmt
|
||||
= name:name() equal() value:expression() {
|
||||
let span = name.span.through(value.span);
|
||||
@@ -140,6 +153,13 @@ peg::parser! {
|
||||
}
|
||||
|
||||
pub rule expression() -> Expr = precedence! {
|
||||
left:(@) [Token {kind:TokenKind::EqualEqual,..}] right:@ {binary(left,BinaryOp::Equal,right)}
|
||||
left:(@) [Token {kind:TokenKind::NotEqual,..}] right:@ {binary(left,BinaryOp::NotEqual,right)}
|
||||
left:(@) [Token {kind:TokenKind::Less,..}] right:@ {binary(left,BinaryOp::Less,right)}
|
||||
left:(@) [Token {kind:TokenKind::LessEqual,..}] right:@ {binary(left,BinaryOp::LessEqual,right)}
|
||||
left:(@) [Token {kind:TokenKind::Greater,..}] right:@ {binary(left,BinaryOp::Greater,right)}
|
||||
left:(@) [Token {kind:TokenKind::GreaterEqual,..}] right:@ {binary(left,BinaryOp::GreaterEqual,right)}
|
||||
--
|
||||
left:(@) plus() right:@ { binary(left, BinaryOp::Add, right) }
|
||||
left:(@) minus() right:@ { binary(left, BinaryOp::Subtract, right) }
|
||||
--
|
||||
|
||||
@@ -59,6 +59,12 @@ peg::parser! {
|
||||
/ ":" { TokenKind::Colon }
|
||||
/ "," { TokenKind::Comma }
|
||||
/ "." { TokenKind::Dot }
|
||||
/ "==" { TokenKind::EqualEqual }
|
||||
/ "!=" { TokenKind::NotEqual }
|
||||
/ "<=" { TokenKind::LessEqual }
|
||||
/ ">=" { TokenKind::GreaterEqual }
|
||||
/ "<" { TokenKind::Less }
|
||||
/ ">" { TokenKind::Greater }
|
||||
/ "=" { TokenKind::Equal }
|
||||
/ "+" { TokenKind::Plus }
|
||||
/ "-" { TokenKind::Minus }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::ast::{
|
||||
Assignment, AstRoot, BinaryOp, Binding, Block, Class, Decl, DeclKind, Expr, ExprKind, Function,
|
||||
InteractiveInput, MemberAssignment, Name, Parameter, Program, ReturnStatement, Stmt, StmtKind,
|
||||
UnaryOp,
|
||||
IfStatement, InteractiveInput, MemberAssignment, Name, Parameter, Program, ReturnStatement,
|
||||
Stmt, StmtKind, UnaryOp, WhileStatement,
|
||||
};
|
||||
use crate::lexer::decode_string;
|
||||
use crate::{Diagnostic, DiagnosticKind, Span, Token, TokenKind, lex};
|
||||
|
||||
@@ -16,6 +16,12 @@ pub enum TokenKind {
|
||||
Comma,
|
||||
Dot,
|
||||
Equal,
|
||||
EqualEqual,
|
||||
NotEqual,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
|
||||
Reference in New Issue
Block a user