Move constancy into Dynamic.

This commit is contained in:
Stephen Chung
2020-12-08 22:47:38 +08:00
parent 8e8069f819
commit f22a04fc74
14 changed files with 501 additions and 430 deletions

View File

@@ -3,12 +3,11 @@
use crate::ast::{
BinaryExpr, CustomExpr, Expr, FnCallExpr, Ident, IdentX, ReturnType, ScriptFnDef, Stmt,
};
use crate::dynamic::Union;
use crate::dynamic::{AccessType, Union};
use crate::engine::{KEYWORD_THIS, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
use crate::module::NamespaceRef;
use crate::optimize::optimize_into_ast;
use crate::optimize::OptimizationLevel;
use crate::scope::EntryType as ScopeEntryType;
use crate::stdlib::{
borrow::Cow,
boxed::Box,
@@ -49,7 +48,7 @@ struct ParseState<'e> {
/// Interned strings.
strings: HashMap<String, ImmutableString>,
/// Encapsulates a local stack with variable names to simulate an actual runtime scope.
stack: Vec<(ImmutableString, ScopeEntryType)>,
stack: Vec<(ImmutableString, AccessType)>,
/// Size of the local variables stack upon entry of the current block scope.
entry_stack_len: usize,
/// Tracks a list of external variables (variables that are not explicitly declared in the scope).
@@ -1291,11 +1290,11 @@ fn make_assignment_stmt<'a>(
},
) = x.as_ref();
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
ScopeEntryType::Normal => {
AccessType::Normal => {
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
}
// Constant values cannot be assigned to
ScopeEntryType::Constant => {
AccessType::Constant => {
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
}
}
@@ -1318,11 +1317,11 @@ fn make_assignment_stmt<'a>(
},
) = x.as_ref();
match state.stack[(state.stack.len() - index.unwrap().get())].1 {
ScopeEntryType::Normal => {
AccessType::Normal => {
Ok(Stmt::Assignment(Box::new((lhs, fn_name.into(), rhs)), pos))
}
// Constant values cannot be assigned to
ScopeEntryType::Constant => {
AccessType::Constant => {
Err(PERR::AssignmentToConstant(name.to_string()).into_err(*name_pos))
}
}
@@ -1811,7 +1810,7 @@ fn parse_custom_syntax(
// Variable searches stop at the first empty variable name.
state.stack.resize(
state.stack.len() + delta as usize,
("".into(), ScopeEntryType::Normal),
("".into(), AccessType::Normal),
);
}
delta if delta < 0 && state.stack.len() <= delta.abs() as usize => state.stack.clear(),
@@ -2110,7 +2109,7 @@ fn parse_for(
let loop_var = state.get_interned_string(name.clone());
let prev_stack_len = state.stack.len();
state.stack.push((loop_var, ScopeEntryType::Normal));
state.stack.push((loop_var, AccessType::Normal));
settings.is_breakable = true;
let body = parse_block(input, state, lib, settings.level_up())?;
@@ -2125,7 +2124,7 @@ fn parse_let(
input: &mut TokenStream,
state: &mut ParseState,
lib: &mut FunctionsLib,
var_type: ScopeEntryType,
var_type: AccessType,
export: bool,
mut settings: ParseSettings,
) -> Result<Stmt, ParseError> {
@@ -2156,16 +2155,16 @@ fn parse_let(
match var_type {
// let name = expr
ScopeEntryType::Normal => {
AccessType::Normal => {
let var_name = state.get_interned_string(name.clone());
state.stack.push((var_name, ScopeEntryType::Normal));
state.stack.push((var_name, AccessType::Normal));
let var_def = Ident::new(name, pos);
Ok(Stmt::Let(Box::new(var_def), init_expr, export, token_pos))
}
// const name = { expr:constant }
ScopeEntryType::Constant => {
AccessType::Constant => {
let var_name = state.get_interned_string(name.clone());
state.stack.push((var_name, ScopeEntryType::Constant));
state.stack.push((var_name, AccessType::Constant));
let var_def = Ident::new(name, pos);
Ok(Stmt::Const(Box::new(var_def), init_expr, export, token_pos))
}
@@ -2232,13 +2231,13 @@ fn parse_export(
match input.peek().unwrap() {
(Token::Let, pos) => {
let pos = *pos;
let mut stmt = parse_let(input, state, lib, ScopeEntryType::Normal, true, settings)?;
let mut stmt = parse_let(input, state, lib, AccessType::Normal, true, settings)?;
stmt.set_position(pos);
return Ok(stmt);
}
(Token::Const, pos) => {
let pos = *pos;
let mut stmt = parse_let(input, state, lib, ScopeEntryType::Constant, true, settings)?;
let mut stmt = parse_let(input, state, lib, AccessType::Constant, true, settings)?;
stmt.set_position(pos);
return Ok(stmt);
}
@@ -2393,7 +2392,7 @@ fn parse_stmt(
lib: &mut FunctionsLib,
mut settings: ParseSettings,
) -> Result<Option<Stmt>, ParseError> {
use ScopeEntryType::{Constant, Normal};
use AccessType::{Constant, Normal};
let (token, token_pos) = match input.peek().unwrap() {
(Token::EOF, pos) => return Ok(Some(Stmt::Noop(*pos))),
@@ -2637,7 +2636,7 @@ fn parse_fn(
return Err(PERR::FnDuplicatedParam(name, s).into_err(pos));
}
let s = state.get_interned_string(s);
state.stack.push((s.clone(), ScopeEntryType::Normal));
state.stack.push((s.clone(), AccessType::Normal));
params.push((s, pos))
}
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
@@ -2770,7 +2769,7 @@ fn parse_anon_fn(
return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos));
}
let s = state.get_interned_string(s);
state.stack.push((s.clone(), ScopeEntryType::Normal));
state.stack.push((s.clone(), AccessType::Normal));
params.push((s, pos))
}
(Token::LexError(err), pos) => return Err(err.into_err(pos)),
@@ -3005,15 +3004,15 @@ impl Engine {
pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
match value.0 {
#[cfg(not(feature = "no_float"))]
Union::Float(value) => Some(Expr::FloatConstant(value, pos)),
Union::Float(value, _) => Some(Expr::FloatConstant(value, pos)),
Union::Unit(_) => Some(Expr::Unit(pos)),
Union::Int(value) => Some(Expr::IntegerConstant(value, pos)),
Union::Char(value) => Some(Expr::CharConstant(value, pos)),
Union::Str(value) => Some(Expr::StringConstant(value, pos)),
Union::Bool(value) => Some(Expr::BoolConstant(value, pos)),
Union::Unit(_, _) => Some(Expr::Unit(pos)),
Union::Int(value, _) => Some(Expr::IntegerConstant(value, pos)),
Union::Char(value, _) => Some(Expr::CharConstant(value, pos)),
Union::Str(value, _) => Some(Expr::StringConstant(value, pos)),
Union::Bool(value, _) => Some(Expr::BoolConstant(value, pos)),
#[cfg(not(feature = "no_index"))]
Union::Array(array) => {
Union::Array(array, _) => {
let items: Vec<_> = array
.into_iter()
.map(|x| map_dynamic_to_expr(x, pos))
@@ -3029,7 +3028,7 @@ pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
}
}
#[cfg(not(feature = "no_object"))]
Union::Map(map) => {
Union::Map(map, _) => {
let items: Vec<_> = map
.into_iter()
.map(|(k, v)| (IdentX::new(k, pos), map_dynamic_to_expr(v, pos)))