implement first parts of member access
This commit is contained in:
parent
dd97937feb
commit
927b0f52c1
|
@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Integer and boolean arrays (scoreboard and data storage)
|
- Integer and boolean arrays (scoreboard and data storage)
|
||||||
- Integer map (scoreboard)
|
- Integer map (scoreboard)
|
||||||
- Boolean map (tag)
|
- Boolean map (tag)
|
||||||
|
- Member access (e.g. `.objective` to get objective name where int is stored)
|
||||||
|
- Return statement
|
||||||
- Example: barebones compiler
|
- Example: barebones compiler
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -26,7 +26,7 @@ zip = ["shulkerbox?/zip"]
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
chksum-md5 = { version = "0.1.0", optional = true }
|
chksum-md5 = { version = "0.1.0", optional = true }
|
||||||
colored = "3.0.0"
|
colored = "3.0.0"
|
||||||
derive_more = { version = "2.0.1", default-features = false, features = ["deref", "deref_mut", "from"] }
|
derive_more = { version = "2.0.1", default-features = false, features = [ "deref", "deref_mut", "from"] }
|
||||||
enum-as-inner = "0.6.0"
|
enum-as-inner = "0.6.0"
|
||||||
getset = "0.1.2"
|
getset = "0.1.2"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
|
@ -35,7 +35,7 @@ pathdiff = "0.2.3"
|
||||||
serde = { version = "1.0.217", features = ["derive"], optional = true }
|
serde = { version = "1.0.217", features = ["derive"], optional = true }
|
||||||
serde_json = { version = "1.0.138", optional = true }
|
serde_json = { version = "1.0.138", optional = true }
|
||||||
# shulkerbox = { version = "0.1.0", default-features = false, optional = true }
|
# shulkerbox = { version = "0.1.0", default-features = false, optional = true }
|
||||||
shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox", rev = "5c4d340162fc16065add448ed387a1ce481c27d6", default-features = false, optional = true }
|
shulkerbox = { git = "https://github.com/moritz-hoelting/shulkerbox", rev = "6ff544131b2518b8c92bc4d2de7682efd7141ec4", default-features = false, optional = true }
|
||||||
strsim = "0.11.1"
|
strsim = "0.11.1"
|
||||||
strum = { version = "0.27.0", features = ["derive"] }
|
strum = { version = "0.27.0", features = ["derive"] }
|
||||||
thiserror = "2.0.11"
|
thiserror = "2.0.11"
|
||||||
|
|
|
@ -623,6 +623,10 @@ impl Primary {
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::MemberAccess(_) => {
|
||||||
|
// TODO:
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Self::Parenthesized(expr) => expr.analyze_semantics(scope, handler),
|
Self::Parenthesized(expr) => expr.analyze_semantics(scope, handler),
|
||||||
Self::Prefix(prefixed) => match prefixed.operator() {
|
Self::Prefix(prefixed) => match prefixed.operator() {
|
||||||
PrefixOperator::LogicalNot(_) => {
|
PrefixOperator::LogicalNot(_) => {
|
||||||
|
@ -680,7 +684,9 @@ impl Primary {
|
||||||
match self {
|
match self {
|
||||||
Self::Boolean(_) => expected == ValueType::Boolean,
|
Self::Boolean(_) => expected == ValueType::Boolean,
|
||||||
Self::Integer(_) => expected == ValueType::Integer,
|
Self::Integer(_) => expected == ValueType::Integer,
|
||||||
Self::StringLiteral(_) | Self::MacroStringLiteral(_) => expected == ValueType::String,
|
Self::StringLiteral(_) | Self::MacroStringLiteral(_) => {
|
||||||
|
matches!(expected, ValueType::String | ValueType::Boolean)
|
||||||
|
}
|
||||||
Self::FunctionCall(_) => matches!(expected, ValueType::Boolean | ValueType::Integer),
|
Self::FunctionCall(_) => matches!(expected, ValueType::Boolean | ValueType::Integer),
|
||||||
Self::Indexed(indexed) => match indexed.object().as_ref() {
|
Self::Indexed(indexed) => match indexed.object().as_ref() {
|
||||||
Self::Identifier(ident) => {
|
Self::Identifier(ident) => {
|
||||||
|
@ -699,6 +705,10 @@ impl Primary {
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
Self::MemberAccess(_) => {
|
||||||
|
// TODO:
|
||||||
|
true
|
||||||
|
}
|
||||||
Self::Identifier(ident) => match scope.get_variable(ident.span.str()) {
|
Self::Identifier(ident) => match scope.get_variable(ident.span.str()) {
|
||||||
Some(VariableType::BooleanStorage) => expected == ValueType::Boolean,
|
Some(VariableType::BooleanStorage) => expected == ValueType::Boolean,
|
||||||
Some(VariableType::ScoreboardValue) => expected == ValueType::Integer,
|
Some(VariableType::ScoreboardValue) => expected == ValueType::Integer,
|
||||||
|
|
|
@ -175,6 +175,7 @@ impl SourceElement for Expression {
|
||||||
/// | Boolean
|
/// | Boolean
|
||||||
/// | StringLiteral
|
/// | StringLiteral
|
||||||
/// | FunctionCall
|
/// | FunctionCall
|
||||||
|
/// | MemberAccess
|
||||||
/// | MacroStringLiteral
|
/// | MacroStringLiteral
|
||||||
/// | LuaCode
|
/// | LuaCode
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -190,6 +191,7 @@ pub enum Primary {
|
||||||
Boolean(Boolean),
|
Boolean(Boolean),
|
||||||
StringLiteral(StringLiteral),
|
StringLiteral(StringLiteral),
|
||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
|
MemberAccess(MemberAccess),
|
||||||
MacroStringLiteral(MacroStringLiteral),
|
MacroStringLiteral(MacroStringLiteral),
|
||||||
Lua(Box<LuaCode>),
|
Lua(Box<LuaCode>),
|
||||||
}
|
}
|
||||||
|
@ -205,6 +207,7 @@ impl SourceElement for Primary {
|
||||||
Self::Boolean(bool) => bool.span(),
|
Self::Boolean(bool) => bool.span(),
|
||||||
Self::StringLiteral(string_literal) => string_literal.span(),
|
Self::StringLiteral(string_literal) => string_literal.span(),
|
||||||
Self::FunctionCall(function_call) => function_call.span(),
|
Self::FunctionCall(function_call) => function_call.span(),
|
||||||
|
Self::MemberAccess(member_access) => member_access.span(),
|
||||||
Self::MacroStringLiteral(macro_string_literal) => macro_string_literal.span(),
|
Self::MacroStringLiteral(macro_string_literal) => macro_string_literal.span(),
|
||||||
Self::Lua(lua_code) => lua_code.span(),
|
Self::Lua(lua_code) => lua_code.span(),
|
||||||
}
|
}
|
||||||
|
@ -443,6 +446,45 @@ impl LuaCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a member access in the syntax tree.
|
||||||
|
///
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
///
|
||||||
|
/// ```ebnf
|
||||||
|
/// MemberAccess:
|
||||||
|
/// Primary '.' Identifier
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct MemberAccess {
|
||||||
|
/// The parent expression
|
||||||
|
#[get = "pub"]
|
||||||
|
parent: Box<Primary>,
|
||||||
|
/// The dot in the middle
|
||||||
|
#[get = "pub"]
|
||||||
|
dot: Punctuation,
|
||||||
|
/// The member being accessed
|
||||||
|
#[get = "pub"]
|
||||||
|
member: Identifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceElement for MemberAccess {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.parent
|
||||||
|
.span()
|
||||||
|
.join(&self.member.span)
|
||||||
|
.expect("invalid span")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemberAccess {
|
||||||
|
/// Dissolves the [`MemberAccess`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Box<Primary>, Punctuation, Identifier) {
|
||||||
|
(self.parent, self.dot, self.member)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parser<'_> {
|
impl Parser<'_> {
|
||||||
/// Parses an [`Expression`]
|
/// Parses an [`Expression`]
|
||||||
///
|
///
|
||||||
|
@ -509,7 +551,7 @@ impl Parser<'_> {
|
||||||
/// - If the parser is not at a valid primary expression.
|
/// - If the parser is not at a valid primary expression.
|
||||||
#[expect(clippy::too_many_lines)]
|
#[expect(clippy::too_many_lines)]
|
||||||
pub fn parse_primary(&mut self, handler: &impl Handler<base::Error>) -> ParseResult<Primary> {
|
pub fn parse_primary(&mut self, handler: &impl Handler<base::Error>) -> ParseResult<Primary> {
|
||||||
match self.stop_at_significant() {
|
let prim = match self.stop_at_significant() {
|
||||||
// prefixed expression with '!' or '-'
|
// prefixed expression with '!' or '-'
|
||||||
Reading::Atomic(Token::Punctuation(punc)) if matches!(punc.punctuation, '!' | '-') => {
|
Reading::Atomic(Token::Punctuation(punc)) if matches!(punc.punctuation, '!' | '-') => {
|
||||||
// eat the prefix
|
// eat the prefix
|
||||||
|
@ -702,6 +744,21 @@ impl Parser<'_> {
|
||||||
|
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
match self.stop_at_significant() {
|
||||||
|
Reading::Atomic(Token::Punctuation(punc)) if punc.punctuation == '.' => {
|
||||||
|
self.forward();
|
||||||
|
|
||||||
|
let member = self.parse_identifier(handler)?;
|
||||||
|
|
||||||
|
Ok(Primary::MemberAccess(MemberAccess {
|
||||||
|
parent: Box::new(prim),
|
||||||
|
dot: punc,
|
||||||
|
member,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
_ => Ok(prim),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,13 @@ use super::{
|
||||||
},
|
},
|
||||||
Scope, TranspileResult, Transpiler, VariableData,
|
Scope, TranspileResult, Transpiler, VariableData,
|
||||||
};
|
};
|
||||||
|
use crate::lexical::token::{Identifier, StringLiteral};
|
||||||
#[cfg(feature = "shulkerbox")]
|
#[cfg(feature = "shulkerbox")]
|
||||||
use crate::{
|
use crate::{
|
||||||
base::{self, source_file::SourceElement, Handler, VoidHandler},
|
base::{self, source_file::SourceElement, Handler, VoidHandler},
|
||||||
lexical::token::MacroStringLiteralPart,
|
lexical::token::MacroStringLiteralPart,
|
||||||
syntax::syntax_tree::expression::{
|
syntax::syntax_tree::expression::{
|
||||||
Binary, BinaryOperator, Expression, PrefixOperator, Primary,
|
Binary, BinaryOperator, Expression, MemberAccess, PrefixOperator, Primary,
|
||||||
},
|
},
|
||||||
transpile::{
|
transpile::{
|
||||||
error::{FunctionArgumentsNotAllowed, MissingValue},
|
error::{FunctionArgumentsNotAllowed, MissingValue},
|
||||||
|
@ -319,6 +320,9 @@ impl Primary {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::MemberAccess(_) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
#[cfg_attr(not(feature = "lua"), expect(unused_variables))]
|
#[cfg_attr(not(feature = "lua"), expect(unused_variables))]
|
||||||
Self::Lua(lua) => {
|
Self::Lua(lua) => {
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
|
@ -379,6 +383,11 @@ impl Primary {
|
||||||
Self::Parenthesized(parenthesized) => {
|
Self::Parenthesized(parenthesized) => {
|
||||||
parenthesized.expression().comptime_eval(scope, handler)
|
parenthesized.expression().comptime_eval(scope, handler)
|
||||||
}
|
}
|
||||||
|
Self::MemberAccess(member_access) => {
|
||||||
|
member_access
|
||||||
|
.parent()
|
||||||
|
.comptime_member_access(member_access, scope, handler)
|
||||||
|
}
|
||||||
Self::Prefix(prefix) => {
|
Self::Prefix(prefix) => {
|
||||||
prefix
|
prefix
|
||||||
.operand()
|
.operand()
|
||||||
|
@ -419,6 +428,176 @@ impl Primary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn comptime_member_access(
|
||||||
|
&self,
|
||||||
|
member_access: &MemberAccess,
|
||||||
|
scope: &Arc<Scope>,
|
||||||
|
handler: &impl Handler<base::Error>,
|
||||||
|
) -> Result<ComptimeValue, NotComptime> {
|
||||||
|
match self {
|
||||||
|
Self::StringLiteral(s) => s.comptime_member_access(member_access, scope, handler),
|
||||||
|
Self::Identifier(ident) => ident.comptime_member_access(member_access, scope, handler),
|
||||||
|
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringLiteral {
|
||||||
|
fn comptime_member_access(
|
||||||
|
&self,
|
||||||
|
member_access: &MemberAccess,
|
||||||
|
_scope: &Arc<Scope>,
|
||||||
|
_handler: &impl Handler<base::Error>,
|
||||||
|
) -> Result<ComptimeValue, NotComptime> {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"length" => Ok(ComptimeValue::Integer(
|
||||||
|
i64::try_from(self.str_content().len())
|
||||||
|
.expect("string literal length should fit in i64"),
|
||||||
|
)),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Identifier {
|
||||||
|
#[expect(clippy::too_many_lines)]
|
||||||
|
fn comptime_member_access(
|
||||||
|
&self,
|
||||||
|
member_access: &MemberAccess,
|
||||||
|
scope: &Arc<Scope>,
|
||||||
|
_handler: &impl Handler<base::Error>,
|
||||||
|
) -> Result<ComptimeValue, NotComptime> {
|
||||||
|
scope.get_variable(self.span.str()).map_or_else(
|
||||||
|
|| {
|
||||||
|
Err(NotComptime {
|
||||||
|
expression: self.span(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|data| match data.as_ref() {
|
||||||
|
VariableData::ComptimeValue { value, .. } => {
|
||||||
|
let value = value.read().unwrap();
|
||||||
|
value.as_ref().map_or_else(
|
||||||
|
|| {
|
||||||
|
Err(NotComptime {
|
||||||
|
expression: self.span(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|value| match value {
|
||||||
|
ComptimeValue::String(s) => match member_access.member().span.str() {
|
||||||
|
"length" => Ok(ComptimeValue::Integer(
|
||||||
|
i64::try_from(s.len())
|
||||||
|
.expect("comptime string length should fit in i64"),
|
||||||
|
)),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: self.span(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
VariableData::BooleanStorage { storage_name, path } => {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"storage" => Ok(ComptimeValue::String(storage_name.to_owned())),
|
||||||
|
"path" => Ok(ComptimeValue::String(path.to_owned())),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableData::BooleanStorageArray {
|
||||||
|
storage_name,
|
||||||
|
paths: _,
|
||||||
|
} => {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"storage" => Ok(ComptimeValue::String(storage_name.to_owned())),
|
||||||
|
"paths" => {
|
||||||
|
// TODO: implement when comptime arrays are implemented
|
||||||
|
Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableData::Function { path, .. } => {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"path" => {
|
||||||
|
#[expect(clippy::option_if_let_else)]
|
||||||
|
if let Some(path) = path.get() {
|
||||||
|
Ok(ComptimeValue::String(path.to_owned()))
|
||||||
|
} else {
|
||||||
|
// TODO: add support for non already compiled functions
|
||||||
|
Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableData::InternalFunction { .. } => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
VariableData::MacroParameter { macro_name, .. } => {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"name" => Ok(ComptimeValue::String(macro_name.to_owned())),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableData::Scoreboard { objective } => match member_access.member().span.str() {
|
||||||
|
"objective" => Ok(ComptimeValue::String(objective.to_owned())),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
VariableData::ScoreboardArray {
|
||||||
|
objective,
|
||||||
|
targets: _,
|
||||||
|
} => {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"objective" => Ok(ComptimeValue::String(objective.to_owned())),
|
||||||
|
"targets" => {
|
||||||
|
// TODO: implement when comptime arrays are implemented
|
||||||
|
Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableData::ScoreboardValue { objective, target } => {
|
||||||
|
match member_access.member().span.str() {
|
||||||
|
"objective" => Ok(ComptimeValue::String(objective.to_owned())),
|
||||||
|
"target" => Ok(ComptimeValue::String(target.to_owned())),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableData::Tag { tag_name } => match member_access.member().span.str() {
|
||||||
|
"name" => Ok(ComptimeValue::String(tag_name.to_owned())),
|
||||||
|
_ => Err(NotComptime {
|
||||||
|
expression: member_access.member().span(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "shulkerbox")]
|
#[cfg(feature = "shulkerbox")]
|
||||||
|
@ -699,6 +878,7 @@ impl Transpiler {
|
||||||
Primary::Parenthesized(parenthesized) => {
|
Primary::Parenthesized(parenthesized) => {
|
||||||
self.transpile_expression(parenthesized.expression(), target, scope, handler)
|
self.transpile_expression(parenthesized.expression(), target, scope, handler)
|
||||||
}
|
}
|
||||||
|
Primary::MemberAccess(_) => todo!(),
|
||||||
Primary::Lua(lua) =>
|
Primary::Lua(lua) =>
|
||||||
{
|
{
|
||||||
#[expect(clippy::option_if_let_else)]
|
#[expect(clippy::option_if_let_else)]
|
||||||
|
@ -1261,6 +1441,7 @@ impl Transpiler {
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Primary::MemberAccess(_) => todo!(),
|
||||||
Primary::Prefix(prefix) => match prefix.operator() {
|
Primary::Prefix(prefix) => match prefix.operator() {
|
||||||
PrefixOperator::LogicalNot(_) => {
|
PrefixOperator::LogicalNot(_) => {
|
||||||
let (cmds, cond) = self.transpile_primary_expression_as_condition(
|
let (cmds, cond) = self.transpile_primary_expression_as_condition(
|
||||||
|
|
|
@ -357,6 +357,7 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expression::Primary(Primary::MemberAccess(_)) => todo!(),
|
||||||
Expression::Primary(
|
Expression::Primary(
|
||||||
Primary::Parenthesized(_)
|
Primary::Parenthesized(_)
|
||||||
| Primary::Prefix(_)
|
| Primary::Prefix(_)
|
||||||
|
|
|
@ -653,6 +653,8 @@ impl Transpiler {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Primary::MemberAccess(_) => todo!(),
|
||||||
|
|
||||||
Primary::Parenthesized(parenthesized) => match parenthesized.expression().as_ref() {
|
Primary::Parenthesized(parenthesized) => match parenthesized.expression().as_ref() {
|
||||||
Expression::Primary(expression) => {
|
Expression::Primary(expression) => {
|
||||||
self.transpile_run_expression(expression, scope, handler)
|
self.transpile_run_expression(expression, scope, handler)
|
||||||
|
@ -660,7 +662,7 @@ impl Transpiler {
|
||||||
Expression::Binary(bin) => match bin.comptime_eval(scope, handler) {
|
Expression::Binary(bin) => match bin.comptime_eval(scope, handler) {
|
||||||
Ok(ComptimeValue::String(cmd)) => Ok(vec![Command::Raw(cmd)]),
|
Ok(ComptimeValue::String(cmd)) => Ok(vec![Command::Raw(cmd)]),
|
||||||
Ok(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd.into())]),
|
Ok(ComptimeValue::MacroString(cmd)) => Ok(vec![Command::UsesMacro(cmd.into())]),
|
||||||
_ => {
|
Ok(_) => {
|
||||||
let err = TranspileError::MismatchedTypes(MismatchedTypes {
|
let err = TranspileError::MismatchedTypes(MismatchedTypes {
|
||||||
expression: bin.span(),
|
expression: bin.span(),
|
||||||
expected_type: ExpectedType::String,
|
expected_type: ExpectedType::String,
|
||||||
|
@ -668,6 +670,11 @@ impl Transpiler {
|
||||||
handler.receive(err.clone());
|
handler.receive(err.clone());
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
Err(not_comptime) => {
|
||||||
|
let err = TranspileError::NotComptime(not_comptime);
|
||||||
|
handler.receive(err.clone());
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue