From d3d6469ce352762e3bd3967bc4472c6b8dfee52c Mon Sep 17 00:00:00 2001 From: Manyfestation <240733973+Manyfestation@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:24:18 +0200 Subject: [PATCH 1/5] feat(debugger): port debugger onto izio spanned-ast core --- silverscript-lang/Cargo.toml | 4 +- silverscript-lang/src/ast.rs | 1376 ++++--- silverscript-lang/src/bin/sil-debug.rs | 35 +- silverscript-lang/src/bin/silverc.rs | 140 +- silverscript-lang/src/compiler.rs | 3395 +++++++++-------- .../src/compiler/debug_recording.rs | 92 +- silverscript-lang/src/debug.rs | 36 +- silverscript-lang/src/debug/session.rs | 66 +- silverscript-lang/src/diagnostic/mod.rs | 5 + silverscript-lang/src/diagnostic/parse.rs | 217 ++ .../src/diagnostic/parse_diagnostics.rs | 178 + silverscript-lang/src/errors.rs | 52 + silverscript-lang/src/lib.rs | 3 + silverscript-lang/src/parser.rs | 18 +- silverscript-lang/src/span.rs | 81 + .../tests/ast_json/require_test.ast.json | 2 +- .../tests/ast_json/yield_test.ast.json | 2 +- silverscript-lang/tests/ast_json_tests.rs | 2 +- silverscript-lang/tests/ast_spans_tests.rs | 60 + .../tests/cashc_valid_examples_tests.rs | 4 +- silverscript-lang/tests/compiler_tests.rs | 83 +- silverscript-lang/tests/date_literal_tests.rs | 14 +- .../tests/debug_session_tests.rs | 42 +- .../tests/parse_diagnostics_tests.rs | 53 + silverscript-lang/tests/parser_tests.rs | 22 + silverscript-lang/tests/silverc_tests.rs | 111 +- .../tests/tutorial_rust_examples_tests.rs | 2 +- 27 files changed, 3897 insertions(+), 2198 deletions(-) create mode 100644 silverscript-lang/src/diagnostic/mod.rs create mode 100644 silverscript-lang/src/diagnostic/parse.rs create mode 100644 silverscript-lang/src/diagnostic/parse_diagnostics.rs create mode 100644 silverscript-lang/src/errors.rs create mode 100644 silverscript-lang/src/span.rs create mode 100644 silverscript-lang/tests/ast_spans_tests.rs create mode 100644 silverscript-lang/tests/parse_diagnostics_tests.rs diff --git a/silverscript-lang/Cargo.toml b/silverscript-lang/Cargo.toml index 746eb26d..02623350 100644 --- a/silverscript-lang/Cargo.toml +++ b/silverscript-lang/Cargo.toml @@ -23,9 +23,9 @@ rand.workspace = true secp256k1.workspace = true thiserror.workspace = true serde = { version = "1.0", features = ["derive"] } -clap = { version = "4.5", features = ["derive"] } -faster-hex = "0.10" serde_json = "1.0" +clap = { version = "4.5.60", features = ["derive"] } +faster-hex = "0.10" [dev-dependencies] kaspa-addresses.workspace = true diff --git a/silverscript-lang/src/ast.rs b/silverscript-lang/src/ast.rs index 07795ce3..d3768eb2 100644 --- a/silverscript-lang/src/ast.rs +++ b/silverscript-lang/src/ast.rs @@ -1,53 +1,96 @@ -use std::collections::HashMap; +use std::fmt; -use pest::Parser; +use chrono::NaiveDateTime; use pest::iterators::Pair; use serde::{Deserialize, Serialize}; -use crate::compiler::CompilerError; -use crate::debug::SourceSpan; -use crate::parser::{Rule, SilverScriptParser}; -use chrono::NaiveDateTime; +use crate::errors::CompilerError; +use crate::parser::{Rule, parse_source_file, parse_type_name as parse_type_name_rule}; +pub use crate::span::{Span, SpanUtils}; + +#[derive(Debug, Clone)] +struct Identifier<'i> { + name: String, + span: Span<'i>, +} #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ContractAst { +pub struct ContractAst<'i> { pub name: String, - pub params: Vec, + pub params: Vec>, #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub fields: Vec, - pub constants: HashMap, - pub functions: Vec, + pub fields: Vec>, + pub constants: Vec>, + pub functions: Vec>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, +} + +impl<'i> fmt::Display for ContractAst<'i> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let pretty = serde_json::to_string_pretty(self).map_err(|_| fmt::Error)?; + f.write_str(&pretty) + } } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ContractFieldAst { +pub struct ContractFieldAst<'i> { pub type_ref: TypeRef, pub name: String, - pub expr: Expr, + pub expr: Expr<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FunctionAst { +pub struct FunctionAst<'i> { pub name: String, - pub params: Vec, - #[serde(default)] + pub params: Vec>, pub entrypoint: bool, #[serde(default)] pub return_types: Vec, - pub body: Vec, + pub body: Vec>, + #[serde(skip_deserializing)] + pub return_type_spans: Vec>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, + #[serde(skip_deserializing)] + pub body_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ParamAst { +pub struct ParamAst<'i> { pub type_ref: TypeRef, pub name: String, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StateBindingAst { +pub struct StateBindingAst<'i> { pub field_name: String, pub type_ref: TypeRef, pub name: String, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub field_span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -122,38 +165,168 @@ impl TypeRef { } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Statement { - #[serde(default, skip_serializing_if = "Option::is_none")] - pub span: Option, - #[serde(flatten)] - pub kind: StatementKind, -} - #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", content = "data", rename_all = "snake_case")] -pub enum StatementKind { - VariableDefinition { type_ref: TypeRef, modifiers: Vec, name: String, expr: Option }, - TupleAssignment { left_type_ref: TypeRef, left_name: String, right_type_ref: TypeRef, right_name: String, expr: Expr }, - ArrayPush { name: String, expr: Expr }, - FunctionCall { name: String, args: Vec }, - FunctionCallAssign { bindings: Vec, name: String, args: Vec }, - StateFunctionCallAssign { bindings: Vec, name: String, args: Vec }, - Assign { name: String, expr: Expr }, - TimeOp { tx_var: TimeVar, expr: Expr, message: Option }, - Require { expr: Expr, message: Option }, - If { condition: Expr, then_branch: Vec, else_branch: Option> }, - For { ident: String, start: Expr, end: Expr, body: Vec }, - Yield { expr: Expr }, - Return { exprs: Vec }, - Console { args: Vec }, +pub enum Statement<'i> { + VariableDefinition { + type_ref: TypeRef, + #[serde(default)] + modifiers: Vec, + name: String, + expr: Option>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + type_span: Span<'i>, + #[serde(skip_deserializing)] + modifier_spans: Vec>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + TupleAssignment { + left_type_ref: TypeRef, + left_name: String, + right_type_ref: TypeRef, + right_name: String, + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + left_type_span: Span<'i>, + #[serde(skip_deserializing)] + left_name_span: Span<'i>, + #[serde(skip_deserializing)] + right_type_span: Span<'i>, + #[serde(skip_deserializing)] + right_name_span: Span<'i>, + }, + ArrayPush { + name: String, + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + FunctionCall { + name: String, + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + FunctionCallAssign { + bindings: Vec>, + name: String, + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + StateFunctionCallAssign { + bindings: Vec>, + name: String, + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + Assign { + name: String, + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + TimeOp { + tx_var: TimeVar, + expr: Expr<'i>, + message: Option, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + tx_var_span: Span<'i>, + #[serde(skip_deserializing)] + message_span: Option>, + }, + Require { + expr: Expr<'i>, + message: Option, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + message_span: Option>, + }, + If { + condition: Expr<'i>, + then_branch: Vec>, + else_branch: Option>>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + then_span: Span<'i>, + #[serde(skip_deserializing)] + else_span: Option>, + }, + For { + ident: String, + start: Expr<'i>, + end: Expr<'i>, + body: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + ident_span: Span<'i>, + #[serde(skip_deserializing)] + body_span: Span<'i>, + }, + Yield { + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + Return { + exprs: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + Console { + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, +} + +impl<'i> Statement<'i> { + pub fn span(&self) -> Span<'i> { + match self { + Statement::VariableDefinition { span, .. } + | Statement::TupleAssignment { span, .. } + | Statement::ArrayPush { span, .. } + | Statement::FunctionCall { span, .. } + | Statement::FunctionCallAssign { span, .. } + | Statement::StateFunctionCallAssign { span, .. } + | Statement::Assign { span, .. } + | Statement::Return { span, .. } + | Statement::TimeOp { span, .. } + | Statement::Require { span, .. } + | Statement::If { span, .. } + | Statement::For { span, .. } + | Statement::Yield { span, .. } + | Statement::Console { span, .. } => *span, + } + } } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", content = "data", rename_all = "snake_case")] -pub enum ConsoleArg { - Identifier(String), - Literal(Expr), +pub enum ConsoleArg<'i> { + Identifier(String, #[serde(skip_deserializing)] Span<'i>), + Literal(Expr<'i>), } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -163,85 +336,200 @@ pub enum TimeVar { TxTime, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -#[serde(tag = "kind", content = "data", rename_all = "snake_case")] -pub enum Expr { - Int(i64), - Bool(bool), - Byte(u8), - String(String), - Identifier(String), - Array(Vec), - Call { name: String, args: Vec }, - New { name: String, args: Vec }, - Split { source: Box, index: Box, part: SplitPart }, - Slice { source: Box, start: Box, end: Box }, - ArrayIndex { source: Box, index: Box }, - Unary { op: UnaryOp, expr: Box }, - Binary { op: BinaryOp, left: Box, right: Box }, - IfElse { condition: Box, then_expr: Box, else_expr: Box }, - Nullary(NullaryOp), - Introspection { kind: IntrospectionKind, index: Box }, - StateObject(Vec), +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Expr<'i> { + // TODO: evaluate splitting kind in two: + // - actual Expressions + // - user defined primitive Values + #[serde(flatten)] + pub kind: ExprKind<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct StateFieldExpr { - pub name: String, - pub expr: Expr, +impl<'i> Expr<'i> { + pub fn new(kind: ExprKind<'i>, span: Span<'i>) -> Self { + Self { kind, span } + } + + pub fn int(value: i64) -> Self { + Self::new(ExprKind::Int(value), Span::default()) + } + + pub fn bool(value: bool) -> Self { + Self::new(ExprKind::Bool(value), Span::default()) + } + + pub fn byte(value: u8) -> Self { + Self::new(ExprKind::Byte(value), Span::default()) + } + + pub fn bytes(value: Vec) -> Self { + Self::new(ExprKind::Array(value.into_iter().map(Expr::byte).collect()), Span::default()) + } + + pub fn string(value: impl Into) -> Self { + Self::new(ExprKind::String(value.into()), Span::default()) + } + + pub fn identifier(value: impl Into) -> Self { + Self::new(ExprKind::Identifier(value.into()), Span::default()) + } + + pub fn call(name: impl Into, args: Vec>) -> Self { + Self::new(ExprKind::Call { name: name.into(), args, name_span: Span::default() }, Span::default()) + } } -impl From for Expr { +impl<'i> From for Expr<'i> { fn from(value: i64) -> Self { - Expr::Int(value) + Expr::int(value) } } -impl From for Expr { +impl<'i> From for Expr<'i> { fn from(value: bool) -> Self { - Expr::Bool(value) + Expr::bool(value) } } -impl From> for Expr { +impl<'i> From> for Expr<'i> { fn from(value: Vec) -> Self { - Expr::Array(value.into_iter().map(Expr::Byte).collect()) + Expr::bytes(value) } } -impl From for Expr { +impl<'i> From for Expr<'i> { fn from(value: String) -> Self { - Expr::String(value) + Expr::string(value) + } +} + +impl<'i> From<&str> for Expr<'i> { + fn from(value: &str) -> Self { + Expr::string(value) + } +} + +impl<'i> From> for Expr<'i> { + fn from(values: Vec) -> Self { + let exprs = values.into_iter().map(Expr::int).collect(); + Expr::new(ExprKind::Array(exprs), Span::default()) } } -impl From> for Expr { - fn from(value: Vec) -> Self { - Expr::Array(value.into_iter().map(Expr::Int).collect()) +impl<'i> From>> for Expr<'i> { + fn from(values: Vec>) -> Self { + Expr::new(ExprKind::Array(values), Span::default()) } } -impl From>> for Expr { - fn from(value: Vec>) -> Self { - Expr::Array(value.into_iter().map(|bytes| Expr::Array(bytes.into_iter().map(Expr::Byte).collect())).collect()) +impl<'i> From>> for Expr<'i> { + fn from(values: Vec>) -> Self { + let exprs = values.into_iter().map(Expr::bytes).collect(); + Expr::new(ExprKind::Array(exprs), Span::default()) } } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "kind", content = "data", rename_all = "snake_case")] +pub enum ExprKind<'i> { + Int(i64), + Bool(bool), + Byte(u8), + String(String), + DateLiteral(i64), + Identifier(String), + Array(Vec>), + Call { + name: String, + args: Vec>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + New { + name: String, + args: Vec>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + Split { + source: Box>, + index: Box>, + part: SplitPart, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + Slice { + source: Box>, + start: Box>, + end: Box>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + ArrayIndex { + source: Box>, + index: Box>, + }, + Unary { + op: UnaryOp, + expr: Box>, + }, + Binary { + op: BinaryOp, + left: Box>, + right: Box>, + }, + IfElse { + condition: Box>, + then_expr: Box>, + else_expr: Box>, + }, + Nullary(NullaryOp), + Introspection { + kind: IntrospectionKind, + index: Box>, + #[serde(skip_deserializing)] + field_span: Span<'i>, + }, + StateObject(Vec>), + NumberWithUnit { + value: i64, + unit: String, + }, + UnarySuffix { + source: Box>, + kind: UnarySuffixKind, + #[serde(skip_deserializing)] + span: Span<'i>, + }, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct StateFieldExpr<'i> { + pub name: String, + pub expr: Expr<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum SplitPart { Left, Right, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum UnaryOp { Not, Neg, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum BinaryOp { Or, @@ -262,7 +550,7 @@ pub enum BinaryOp { Mod, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum NullaryOp { ActiveInputIndex, @@ -275,25 +563,44 @@ pub enum NullaryOp { TxLockTime, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum IntrospectionKind { InputValue, InputScriptPubKey, InputSigScript, + /// TODO: not supported yet + InputOutpointTransactionHash, + /// TODO: not supported yet + InputOutpointIndex, + /// TODO: not supported yet + InputSequenceNumber, OutputValue, OutputScriptPubKey, } -fn validate_user_identifier(name: &str) -> Result<(), CompilerError> { - if name.starts_with("__") { - return Err(CompilerError::Unsupported("identifier cannot start with '__'".to_string())); - } - Ok(()) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ConstantAst<'i> { + pub type_ref: TypeRef, + pub name: String, + pub expr: Expr<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum UnarySuffixKind { + Reverse, + Length, } pub fn parse_type_ref(type_name: &str) -> Result { - let mut pairs = SilverScriptParser::parse(Rule::type_name, type_name)?; + let mut pairs = parse_type_name_rule(type_name)?; let pair = pairs.next().ok_or_else(|| CompilerError::Unsupported("missing type name".to_string()))?; parse_type_name_pair(pair) } @@ -303,7 +610,7 @@ fn parse_type_name_pair(pair: Pair<'_, Rule>) -> Result return Err(CompilerError::Unsupported("expected type name".to_string())); } - let mut inner = pair.clone().into_inner(); + let mut inner = pair.into_inner(); let base = match inner.next().ok_or_else(|| CompilerError::Unsupported("missing base type".to_string()))?.as_str() { "int" => TypeBase::Int, "bool" => TypeBase::Bool, @@ -329,9 +636,7 @@ fn parse_type_name_pair(pair: Pair<'_, Rule>) -> Result if let Ok(size) = raw.parse::() { ArrayDim::Fixed(size) } else { ArrayDim::Constant(raw.to_string()) } } Rule::Identifier => ArrayDim::Constant(size_pair.as_str().to_string()), - _ => { - return Err(CompilerError::Unsupported("invalid array dimension".to_string())); - } + _ => return Err(CompilerError::Unsupported("invalid array dimension".to_string())), }, }; array_dims.push(dim); @@ -340,8 +645,8 @@ fn parse_type_name_pair(pair: Pair<'_, Rule>) -> Result Ok(TypeRef { base, array_dims }) } -pub fn parse_contract_ast(source: &str) -> Result { - let mut pairs = SilverScriptParser::parse(Rule::source_file, source)?; +pub fn parse_contract_ast<'i>(source: &'i str) -> Result, CompilerError> { + let mut pairs = parse_source_file(source)?; let source_pair = pairs.next().ok_or_else(|| CompilerError::Unsupported("empty source".to_string()))?; let mut contract = None; @@ -354,15 +659,19 @@ pub fn parse_contract_ast(source: &str) -> Result { contract.ok_or_else(|| CompilerError::Unsupported("no contract definition".to_string())) } -fn parse_contract_definition(pair: Pair<'_, Rule>) -> Result { +fn parse_contract_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing contract name".to_string()))?; let params_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing contract parameters".to_string()))?; + + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; let params = parse_typed_parameter_list(params_pair)?; let mut functions = Vec::new(); let mut fields = Vec::new(); - let mut constants: HashMap = HashMap::new(); + let mut constants = Vec::new(); for item_pair in inner { if item_pair.as_rule() != Rule::contract_item { @@ -371,289 +680,354 @@ fn parse_contract_definition(pair: Pair<'_, Rule>) -> Result { - functions.push(parse_function_definition(inner_item)?); - } - Rule::contract_field_definition => { - let mut field_inner = inner_item.into_inner(); - let type_pair = field_inner.next().ok_or_else(|| CompilerError::Unsupported("missing field type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; - let name_pair = field_inner.next().ok_or_else(|| CompilerError::Unsupported("missing field name".to_string()))?; - validate_user_identifier(name_pair.as_str())?; - let expr_pair = - field_inner.next().ok_or_else(|| CompilerError::Unsupported("missing field initializer".to_string()))?; - let expr = parse_expression(expr_pair)?; - fields.push(ContractFieldAst { type_ref, name: name_pair.as_str().to_string(), expr }); - } - Rule::constant_definition => { - let mut const_inner = inner_item.into_inner(); - let _type_name = - const_inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant type".to_string()))?; - let name_pair = - const_inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant name".to_string()))?; - validate_user_identifier(name_pair.as_str())?; - let expr_pair = - const_inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant initializer".to_string()))?; - let expr = parse_expression(expr_pair)?; - constants.insert(name_pair.as_str().to_string(), expr); - } + Rule::function_definition => functions.push(parse_function_definition(inner_item)?), + Rule::contract_field_definition => fields.push(parse_contract_field_definition(inner_item)?), + Rule::constant_definition => constants.push(parse_constant_definition(inner_item)?), _ => {} } } } - Ok(ContractAst { name: name_pair.as_str().to_string(), params, fields, constants, functions }) + Ok(ContractAst { name, params, fields, constants, functions, span, name_span }) } -fn parse_function_definition(pair: Pair<'_, Rule>) -> Result { +fn parse_function_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); - let mut entrypoint = false; - let name_pair = match inner.next() { - Some(pair) if pair.as_rule() == Rule::entrypoint => { - entrypoint = true; - inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))? - } - Some(pair) => pair, - None => return Err(CompilerError::Unsupported("missing function name".to_string())), + + let first = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?; + let (entrypoint, name_pair) = if first.as_rule() == Rule::entrypoint { + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?; + (true, name_pair) + } else { + (false, first) }; + let params_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function parameters".to_string()))?; let params = parse_typed_parameter_list(params_pair)?; + let mut return_types = Vec::new(); + let mut return_type_spans = Vec::new(); if let Some(next) = inner.peek() { if next.as_rule() == Rule::return_type_list { let return_pair = inner.next().expect("checked"); - return_types = parse_return_type_list(return_pair)?; + let (types, spans) = parse_return_type_list(return_pair)?; + return_types = types; + return_type_spans = spans; } } + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + let mut body = Vec::new(); - for stmt in inner { - body.push(parse_statement(stmt)?); + let mut body_span: Option> = None; + for stmt_pair in inner { + let stmt = parse_statement(stmt_pair)?; + let stmt_span = stmt.span(); + body_span = Some(match body_span { + None => stmt_span, + Some(prev) => prev.join(&stmt_span), + }); + body.push(stmt); } + let body_span = body_span.unwrap_or(span); - Ok(FunctionAst { name: name_pair.as_str().to_string(), params, entrypoint, return_types, body }) + Ok(FunctionAst { name, entrypoint, params, return_types, return_type_spans, body, span, name_span, body_span }) } -fn parse_statement(pair: Pair<'_, Rule>) -> Result { - if pair.as_rule() == Rule::statement { - if let Some(inner) = pair.into_inner().next() { - return parse_statement(inner); - } - return Err(CompilerError::Unsupported("empty statement".to_string())); - } +fn parse_constant_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant type".to_string()))?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant name".to_string()))?; + let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant initializer".to_string()))?; - let span = Some(SourceSpan::from(pair.as_span())); - let kind = match pair.as_rule() { + let expr = parse_expression(expr_pair)?; + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + + Ok(ConstantAst { type_ref, name, expr, span, type_span, name_span }) +} + +fn parse_contract_field_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing field type".to_string()))?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing field name".to_string()))?; + let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing field initializer".to_string()))?; + + let expr = parse_expression(expr_pair)?; + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + + Ok(ContractFieldAst { type_ref, name, expr, span, type_span, name_span }) +} + +fn parse_statement<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + match pair.as_rule() { + Rule::statement => { + if let Some(inner) = pair.into_inner().next() { + parse_statement(inner) + } else { + Err(CompilerError::Unsupported("empty statement".to_string()).with_span(&span)) + } + } Rule::variable_definition => { let mut inner = pair.into_inner(); - let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; + let type_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable type".to_string()).with_span(&span))?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair).map_err(|err| err.with_span(&span))?; let mut modifiers = Vec::new(); + let mut modifier_spans = Vec::new(); while let Some(p) = inner.peek() { if p.as_rule() != Rule::modifier { break; } - modifiers.push(inner.next().expect("checked").as_str().to_string()); + let modifier = inner.next().expect("checked"); + modifiers.push(modifier.as_str().to_string()); + modifier_spans.push(Span::from(modifier.as_span())); } - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable name".to_string()))?; - validate_user_identifier(ident.as_str())?; - let expr = inner.next().map(parse_expression).transpose()?; - StatementKind::VariableDefinition { type_ref, modifiers, name: ident.as_str().to_string(), expr } + let ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable name".to_string()).with_span(&span))?; + let Identifier { name, span: name_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + let expr = match inner.next() { + Some(expr_pair) => Some(parse_expression(expr_pair).map_err(|err| err.with_span(&span))?), + None => None, + }; + Ok(Statement::VariableDefinition { type_ref, modifiers, name, expr, span, type_span, modifier_spans, name_span }) } Rule::tuple_assignment => { let mut inner = pair.into_inner(); - let left_type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple type".to_string()))?; - let left_type_ref = parse_type_name_pair(left_type_pair)?; - let left_ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple name".to_string()))?; - let right_type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple type".to_string()))?; - let right_type_ref = parse_type_name_pair(right_type_pair)?; - let right_ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple name".to_string()))?; - validate_user_identifier(left_ident.as_str())?; - validate_user_identifier(right_ident.as_str())?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple expression".to_string()))?; - - let expr = parse_expression(expr_pair)?; - StatementKind::TupleAssignment { + let left_type_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple type".to_string()).with_span(&span))?; + let left_ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple name".to_string()).with_span(&span))?; + let right_type_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple type".to_string()).with_span(&span))?; + let right_ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple name".to_string()).with_span(&span))?; + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple expression".to_string()).with_span(&span))?; + + let Identifier { name: left_name, span: left_name_span } = + parse_identifier(left_ident).map_err(|err| err.with_span(&span))?; + let Identifier { name: right_name, span: right_name_span } = + parse_identifier(right_ident).map_err(|err| err.with_span(&span))?; + + let right_type_span = Span::from(right_type_pair.as_span()); + let right_type_ref = parse_type_name_pair(right_type_pair).map_err(|err| err.with_span(&span))?; + + let left_type_span = Span::from(left_type_pair.as_span()); + let left_type_ref = parse_type_name_pair(left_type_pair).map_err(|err| err.with_span(&span))?; + + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::TupleAssignment { left_type_ref, - left_name: left_ident.as_str().to_string(), + left_name, right_type_ref, - right_name: right_ident.as_str().to_string(), + right_name, expr, - } + span, + left_type_span, + left_name_span, + right_type_span, + right_name_span, + }) } Rule::push_statement => { let mut inner = pair.into_inner(); - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing push target".to_string()))?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing push expression".to_string()))?; - let expr = parse_expression(expr_pair)?; - StatementKind::ArrayPush { name: ident.as_str().to_string(), expr } + let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing push target".to_string()).with_span(&span))?; + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing push expression".to_string()).with_span(&span))?; + let Identifier { name, span: name_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::ArrayPush { name, expr, span, name_span }) + } + Rule::function_call_assignment => { + let mut inner = pair.into_inner(); + let mut bindings = Vec::new(); + while let Some(p) = inner.peek() { + if p.as_rule() != Rule::typed_binding { + break; + } + let binding = inner.next().expect("checked"); + bindings.push(parse_typed_binding(binding).map_err(|err| err.with_span(&span))?); + } + let call_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()).with_span(&span))?; + let (Identifier { name, span: name_span }, args) = + parse_function_call_parts(call_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::FunctionCallAssign { bindings, name, args, span, name_span }) + } + Rule::state_function_call_assignment => { + let mut inner = pair.into_inner(); + let mut bindings = Vec::new(); + while let Some(p) = inner.peek() { + if p.as_rule() != Rule::state_typed_binding { + break; + } + let binding = inner.next().expect("checked"); + bindings.push(parse_state_typed_binding(binding).map_err(|err| err.with_span(&span))?); + } + let call_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()).with_span(&span))?; + let (Identifier { name, span: name_span }, args) = + parse_function_call_parts(call_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::StateFunctionCallAssign { bindings, name, args, span, name_span }) + } + Rule::call_statement => { + let mut inner = pair.into_inner(); + let call_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing call statement".to_string()).with_span(&span))?; + let (Identifier { name, span: name_span }, args) = + parse_function_call_parts(call_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::FunctionCall { name, args, span, name_span }) } Rule::assign_statement => { let mut inner = pair.into_inner(); - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing assignment name".to_string()))?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing assignment expression".to_string()))?; - let expr = parse_expression(expr_pair)?; - StatementKind::Assign { name: ident.as_str().to_string(), expr } + let ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing assignment name".to_string()).with_span(&span))?; + let expr_pair = inner + .next() + .ok_or_else(|| CompilerError::Unsupported("missing assignment expression".to_string()).with_span(&span))?; + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + let Identifier { name, span: name_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + Ok(Statement::Assign { name, expr, span, name_span }) + } + Rule::return_statement => { + let mut inner = pair.into_inner(); + let list_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing return values".to_string()).with_span(&span))?; + let exprs = parse_expression_list(list_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::Return { exprs, span }) } Rule::time_op_statement => { let mut inner = pair.into_inner(); - let tx_var = inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op variable".to_string()))?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op expression".to_string()))?; - let message = inner.next().map(parse_require_message).transpose()?; - - let expr = parse_expression(expr_pair)?; - let tx_var = match tx_var.as_str() { + let tx_var = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op variable".to_string()).with_span(&span))?; + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op expression".to_string()).with_span(&span))?; + let message = inner.next().map(parse_require_message).transpose().map_err(|err| err.with_span(&span))?; + + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + let tx_var_span = Span::from(tx_var.as_span()); + let tx_var_value = match tx_var.as_str() { "this.age" => TimeVar::ThisAge, "tx.time" => TimeVar::TxTime, - other => return Err(CompilerError::Unsupported(format!("unsupported time variable: {other}"))), + other => { + return Err(CompilerError::Unsupported(format!("unsupported time variable: {other}")).with_span(&tx_var_span)); + } }; - StatementKind::TimeOp { tx_var, expr, message } + let (message, message_span) = message.unzip(); + Ok(Statement::TimeOp { tx_var: tx_var_value, expr, message, span, tx_var_span, message_span }) } Rule::require_statement => { let mut inner = pair.into_inner(); - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing require expression".to_string()))?; - let message = inner.next().map(parse_require_message).transpose()?; - let expr = parse_expression(expr_pair)?; - StatementKind::Require { expr, message } + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing require expression".to_string()).with_span(&span))?; + let message = inner.next().map(parse_require_message).transpose().map_err(|err| err.with_span(&span))?; + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + let (message, message_span) = message.unzip(); + Ok(Statement::Require { expr, message, span, message_span }) } Rule::if_statement => { let mut inner = pair.into_inner(); - let cond_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing if condition".to_string()))?; - let cond_expr = parse_expression(cond_pair)?; - let then_block = inner.next().ok_or_else(|| CompilerError::Unsupported("missing if block".to_string()))?; - let then_branch = parse_block(then_block)?; - let else_branch = inner.next().map(parse_block).transpose()?; - StatementKind::If { condition: cond_expr, then_branch, else_branch } - } - Rule::call_statement => { - let mut inner = pair.into_inner(); - let call_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()))?; - match parse_function_call(call_pair)? { - Expr::Call { name, args } => StatementKind::FunctionCall { name, args }, - _ => return Err(CompilerError::Unsupported("function call expected".to_string())), - } - } - Rule::function_call_assignment => { - let mut bindings = Vec::new(); - let mut call_pair = None; - for item in pair.into_inner() { - if item.as_rule() == Rule::typed_binding { - let mut inner = item.into_inner(); - let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; - let name = inner - .next() - .ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))? - .as_str() - .to_string(); - validate_user_identifier(&name)?; - bindings.push(ParamAst { type_ref, name }); - } else if item.as_rule() == Rule::function_call { - call_pair = Some(item); - } - } - let call_pair = call_pair.ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()))?; - match parse_function_call(call_pair)? { - Expr::Call { name, args } => StatementKind::FunctionCallAssign { bindings, name, args }, - _ => return Err(CompilerError::Unsupported("function call expected".to_string())), - } - } - Rule::state_function_call_assignment => { - let mut bindings = Vec::new(); - let mut call_pair = None; - for item in pair.into_inner() { - if item.as_rule() == Rule::state_typed_binding { - let mut inner = item.into_inner(); - let field_name = inner - .next() - .ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))? - .as_str() - .to_string(); - let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; - let name = inner - .next() - .ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))? - .as_str() - .to_string(); - validate_user_identifier(&field_name)?; - validate_user_identifier(&name)?; - bindings.push(StateBindingAst { field_name, type_ref, name }); - } else if item.as_rule() == Rule::function_call { - call_pair = Some(item); - } - } - let call_pair = call_pair.ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()))?; - match parse_function_call(call_pair)? { - Expr::Call { name, args } => StatementKind::StateFunctionCallAssign { bindings, name, args }, - _ => return Err(CompilerError::Unsupported("function call expected".to_string())), - } + let cond_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing if condition".to_string()).with_span(&span))?; + let cond_expr = parse_expression(cond_pair).map_err(|err| err.with_span(&span))?; + let then_block = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing if block".to_string()).with_span(&span))?; + let (then_branch, then_span) = parse_block(then_block).map_err(|err| err.with_span(&span))?; + let else_data = inner.next().map(parse_block).transpose().map_err(|err| err.with_span(&span))?; + let (else_branch, else_span) = match else_data { + Some((branch, span)) => (Some(branch), Some(span)), + None => (None, None), + }; + Ok(Statement::If { condition: cond_expr, then_branch, else_branch, span, then_span, else_span }) } Rule::for_statement => { let mut inner = pair.into_inner(); - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop identifier".to_string()))?; - validate_user_identifier(ident.as_str())?; - let start_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop start".to_string()))?; - let end_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop end".to_string()))?; - let block_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop body".to_string()))?; - - let start_expr = parse_expression(start_pair)?; - let end_expr = parse_expression(end_pair)?; - let body = parse_block(block_pair)?; - - StatementKind::For { ident: ident.as_str().to_string(), start: start_expr, end: end_expr, body } + let ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop identifier".to_string()).with_span(&span))?; + let start_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop start".to_string()).with_span(&span))?; + let end_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop end".to_string()).with_span(&span))?; + let block_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop body".to_string()).with_span(&span))?; + + let start_expr = parse_expression(start_pair).map_err(|err| err.with_span(&span))?; + let end_expr = parse_expression(end_pair).map_err(|err| err.with_span(&span))?; + let (body, body_span) = parse_block(block_pair).map_err(|err| err.with_span(&span))?; + let Identifier { name: ident, span: ident_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + + Ok(Statement::For { ident, start: start_expr, end: end_expr, body, span, ident_span, body_span }) } Rule::yield_statement => { let mut inner = pair.into_inner(); - let list_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing yield arguments".to_string()))?; - let args = parse_expression_list(list_pair)?; + let list_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing yield arguments".to_string()).with_span(&span))?; + let args = parse_expression_list(list_pair).map_err(|err| err.with_span(&span))?; if args.len() != 1 { - return Err(CompilerError::Unsupported("yield() expects a single argument".to_string())); + return Err(CompilerError::Unsupported("yield() expects a single argument".to_string()).with_span(&span)); } - StatementKind::Yield { expr: args[0].clone() } - } - Rule::return_statement => { - let mut inner = pair.into_inner(); - let list_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing return arguments".to_string()))?; - let args = parse_expression_list(list_pair)?; - if args.is_empty() { - return Err(CompilerError::Unsupported("return() expects at least one argument".to_string())); - } - StatementKind::Return { exprs: args } + Ok(Statement::Yield { expr: args[0].clone(), span }) } Rule::console_statement => { let mut inner = pair.into_inner(); - let list_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing console arguments".to_string()))?; - let args = parse_console_parameter_list(list_pair)?; - StatementKind::Console { args } + let list_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing console arguments".to_string()).with_span(&span))?; + let args = parse_console_parameter_list(list_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::Console { args, span }) } - _ => return Err(CompilerError::Unsupported(format!("unexpected statement: {:?}", pair.as_rule()))), - }; - - Ok(Statement { span, kind }) + _ => Err(CompilerError::Unsupported(format!("unexpected statement: {:?}", pair.as_rule())).with_span(&span)), + } } -fn parse_block(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_block<'i>(pair: Pair<'i, Rule>) -> Result<(Vec>, Span<'i>), CompilerError> { + let span = Span::from(pair.as_span()); match pair.as_rule() { Rule::block => { let mut statements = Vec::new(); - for stmt in pair.into_inner() { - statements.push(parse_statement(stmt)?); + let mut block_span: Option> = None; + for stmt_pair in pair.into_inner() { + let stmt = parse_statement(stmt_pair)?; + let stmt_span = stmt.span(); + block_span = Some(match block_span { + None => stmt_span, + Some(prev) => prev.join(&stmt_span), + }); + statements.push(stmt); } - Ok(statements) + Ok((statements, block_span.unwrap_or(span))) + } + _ => { + let stmt = parse_statement(pair)?; + let stmt_span = stmt.span(); + Ok((vec![stmt], stmt_span)) } - _ => Ok(vec![parse_statement(pair)?]), } } -fn parse_console_parameter_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_console_parameter_list<'i>(pair: Pair<'i, Rule>) -> Result>, CompilerError> { let mut args = Vec::new(); + for param in pair.into_inner() { let value = if param.as_rule() == Rule::console_parameter { single_inner(param)? } else { param }; match value.as_rule() { - Rule::Identifier => args.push(ConsoleArg::Identifier(value.as_str().to_string())), + Rule::Identifier => { + let Identifier { name, span } = parse_identifier(value)?; + args.push(ConsoleArg::Identifier(name, span)); + } Rule::literal => args.push(ConsoleArg::Literal(parse_literal(single_inner(value)?)?)), _ => return Err(CompilerError::Unsupported("console.log arguments not supported".to_string())), } @@ -661,15 +1035,45 @@ fn parse_console_parameter_list(pair: Pair<'_, Rule>) -> Result, Ok(args) } -fn parse_require_message(pair: Pair<'_, Rule>) -> Result { +fn parse_typed_binding<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; + let ident_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))?; + + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + let Identifier { name, span: name_span } = parse_identifier(ident_pair)?; + + Ok(ParamAst { type_ref, name, span, type_span, name_span }) +} + +fn parse_require_message<'i>(pair: Pair<'i, Rule>) -> Result<(String, Span<'i>), CompilerError> { let inner = single_inner(pair)?; match parse_string_literal(inner)? { - Expr::String(value) => Ok(value), + Expr { kind: ExprKind::String(value), span } => Ok((value, span)), _ => Err(CompilerError::Unsupported("require message must be a string literal".to_string())), } } -fn parse_expression(pair: Pair<'_, Rule>) -> Result { +fn parse_state_typed_binding<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let field_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))?; + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; + let ident_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))?; + + let Identifier { name: field_name, span: field_span } = parse_identifier(field_pair)?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + let Identifier { name, span: name_span } = parse_identifier(ident_pair)?; + + Ok(StateBindingAst { field_name, type_ref, name, span, field_span, type_span, name_span }) +} + +fn parse_expression<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { match pair.as_rule() { Rule::expression => parse_expression(single_inner(pair)?), Rule::logical_or => parse_infix(pair, parse_expression, map_logical_or), @@ -687,11 +1091,14 @@ fn parse_expression(pair: Pair<'_, Rule>) -> Result { Rule::parenthesized => parse_expression(single_inner(pair)?), Rule::literal => parse_literal(single_inner(pair)?), Rule::number_literal => parse_number_literal(pair), - Rule::NumberLiteral => parse_number(pair.as_str()), - Rule::BooleanLiteral => Ok(Expr::Bool(pair.as_str() == "true")), - Rule::HexLiteral => parse_hex_literal(pair.as_str()), - Rule::Identifier => Ok(Expr::Identifier(pair.as_str().to_string())), - Rule::NullaryOp => parse_nullary(pair.as_str()), + Rule::NumberLiteral => parse_number_expr(pair), + Rule::BooleanLiteral => Ok(Expr::new(ExprKind::Bool(pair.as_str() == "true"), Span::from(pair.as_span()))), + Rule::HexLiteral => parse_hex_literal(pair), + Rule::Identifier => { + let Identifier { name, span } = parse_identifier(pair)?; + Ok(Expr::new(ExprKind::Identifier(name), span)) + } + Rule::NullaryOp => parse_nullary(pair.as_str(), Span::from(pair.as_span())), Rule::introspection => parse_introspection(pair), Rule::array => parse_array(pair), Rule::function_call => parse_function_call(pair), @@ -710,7 +1117,8 @@ fn parse_expression(pair: Pair<'_, Rule>) -> Result { } } -fn parse_unary(pair: Pair<'_, Rule>) -> Result { +fn parse_unary<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); let mut ops = Vec::new(); while let Some(op) = inner.peek() { @@ -728,22 +1136,24 @@ fn parse_unary(pair: Pair<'_, Rule>) -> Result { let mut expr = parse_expression(inner.next().ok_or_else(|| CompilerError::Unsupported("missing unary operand".to_string()))?)?; for op in ops.into_iter().rev() { - expr = Expr::Unary { op, expr: Box::new(expr) }; + expr = Expr::new(ExprKind::Unary { op, expr: Box::new(expr) }, span); } Ok(expr) } -fn parse_postfix(pair: Pair<'_, Rule>) -> Result { +fn parse_postfix<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { let mut inner = pair.into_inner(); let primary = inner.next().ok_or_else(|| CompilerError::Unsupported("missing primary in postfix".to_string()))?; let mut expr = parse_primary(primary)?; for postfix in inner { + let postfix_span = Span::from(postfix.as_span()); match postfix.as_rule() { Rule::split_call => { let mut split_inner = postfix.into_inner(); let index_expr = split_inner.next().ok_or_else(|| CompilerError::Unsupported("missing split index".to_string()))?; let index = Box::new(parse_expression(index_expr)?); - expr = Expr::Split { source: Box::new(expr), index, part: SplitPart::Left }; + let span = expr.span.join(&postfix_span); + expr = Expr::new(ExprKind::Split { source: Box::new(expr), index, part: SplitPart::Left, span: postfix_span }, span); } Rule::slice_call => { let mut slice_inner = postfix.into_inner(); @@ -751,34 +1161,39 @@ fn parse_postfix(pair: Pair<'_, Rule>) -> Result { let end_expr = slice_inner.next().ok_or_else(|| CompilerError::Unsupported("missing slice end".to_string()))?; let start = Box::new(parse_expression(start_expr)?); let end = Box::new(parse_expression(end_expr)?); - expr = Expr::Slice { source: Box::new(expr), start, end }; + let span = expr.span.join(&postfix_span); + expr = Expr::new(ExprKind::Slice { source: Box::new(expr), start, end, span: postfix_span }, span); } Rule::tuple_index => { let mut index_inner = postfix.into_inner(); - let index_expr = index_inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple index".to_string()))?; - let index = parse_expression(index_expr)?; - match (&expr, &index) { - (Expr::Split { source, index: split_index, .. }, Expr::Int(0)) => { - expr = Expr::Split { source: source.clone(), index: split_index.clone(), part: SplitPart::Left }; - } - (Expr::Split { source, index: split_index, .. }, Expr::Int(1)) => { - expr = Expr::Split { source: source.clone(), index: split_index.clone(), part: SplitPart::Right }; - } - (Expr::Split { .. }, _) => { - return Err(CompilerError::Unsupported("tuple index must be 0 or 1".to_string())); - } - _ => { - expr = Expr::ArrayIndex { source: Box::new(expr), index: Box::new(index) }; - } + let index_pair = index_inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple index".to_string()))?; + let index_expr = parse_expression(index_pair)?; + let index_span = index_expr.span; + let span = expr.span.join(&postfix_span); + if let ExprKind::Split { source, index: split_index, span: split_span, .. } = &expr.kind { + let part = match index_expr.kind { + ExprKind::Int(0) => SplitPart::Left, + ExprKind::Int(1) => SplitPart::Right, + _ => { + return Err(CompilerError::Unsupported("split() index must be 0 or 1".to_string()).with_span(&index_span)); + } + }; + expr = Expr::new( + ExprKind::Split { source: source.clone(), index: split_index.clone(), part, span: *split_span }, + span, + ); + } else { + expr = Expr::new(ExprKind::ArrayIndex { source: Box::new(expr), index: Box::new(index_expr) }, span); } } Rule::unary_suffix => { - let text = postfix.as_str(); - if text.ends_with("length") { - expr = Expr::Call { name: "length".to_string(), args: vec![expr] }; - } else { - return Err(CompilerError::Unsupported("postfix operators are not supported".to_string())); - } + let kind = match postfix.as_str() { + ".reverse()" => UnarySuffixKind::Reverse, + ".length" => UnarySuffixKind::Length, + other => return Err(CompilerError::Unsupported(format!("unknown unary suffix '{other}'"))), + }; + let span = expr.span.join(&postfix_span); + expr = Expr::new(ExprKind::UnarySuffix { source: Box::new(expr), kind, span: postfix_span }, span); } _ => { return Err(CompilerError::Unsupported("postfix operators are not supported".to_string())); @@ -788,39 +1203,51 @@ fn parse_postfix(pair: Pair<'_, Rule>) -> Result { Ok(expr) } -fn parse_typed_parameter_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_typed_parameter_list<'i>(pair: Pair<'i, Rule>) -> Result>, CompilerError> { let mut params = Vec::new(); for param in pair.into_inner() { if param.as_rule() != Rule::parameter { continue; } + + let param_span = Span::from(param.as_span()); let mut inner = param.into_inner(); + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing parameter type".to_string()))?; + let ident_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing parameter name".to_string()))?; + + let Identifier { name, span: name_span } = parse_identifier(ident_pair)?; + let type_span = Span::from(type_pair.as_span()); let type_ref = parse_type_name_pair(type_pair)?; - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing parameter name".to_string()))?.as_str().to_string(); - validate_user_identifier(&ident)?; - params.push(ParamAst { type_ref, name: ident }); + + params.push(ParamAst { type_ref, name, span: param_span, type_span, name_span }); } Ok(params) } -fn parse_return_type_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { - let mut types = Vec::new(); - for item in pair.into_inner() { - if item.as_rule() == Rule::type_name { - let type_ref = parse_type_name_pair(item)?; - types.push(type_ref); +fn parse_return_type_list<'i>(pair: Pair<'i, Rule>) -> Result<(Vec, Vec>), CompilerError> { + let mut return_types = Vec::new(); + let mut return_spans = Vec::new(); + for user_type in pair.into_inner() { + if user_type.as_rule() != Rule::type_name { + continue; } + let type_span = Span::from(user_type.as_span()); + return_types.push(parse_type_name_pair(user_type)?); + return_spans.push(type_span); } - Ok(types) + Ok((return_types, return_spans)) } -fn parse_primary(pair: Pair<'_, Rule>) -> Result { +fn parse_primary<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { match pair.as_rule() { Rule::parenthesized => parse_expression(single_inner(pair)?), Rule::literal => parse_literal(single_inner(pair)?), - Rule::Identifier => Ok(Expr::Identifier(pair.as_str().to_string())), - Rule::NullaryOp => parse_nullary(pair.as_str()), + Rule::Identifier => { + let Identifier { name, span } = parse_identifier(pair)?; + Ok(Expr::new(ExprKind::Identifier(name), span)) + } + Rule::NullaryOp => parse_nullary(pair.as_str(), Span::from(pair.as_span())), Rule::introspection => parse_introspection(pair), Rule::array => parse_array(pair), Rule::function_call => parse_function_call(pair), @@ -832,87 +1259,115 @@ fn parse_primary(pair: Pair<'_, Rule>) -> Result { } } -fn parse_state_object(pair: Pair<'_, Rule>) -> Result { +fn parse_state_object<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut fields = Vec::new(); for field_pair in pair.into_inner() { if field_pair.as_rule() != Rule::state_entry { continue; } + let field_span = Span::from(field_pair.as_span()); let mut inner = field_pair.into_inner(); - let name = - inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))?.as_str().to_string(); - validate_user_identifier(&name)?; + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))?; let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field expression".to_string()))?; + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; let expr = parse_expression(expr_pair)?; - fields.push(StateFieldExpr { name, expr }); + fields.push(StateFieldExpr { name, expr, span: field_span, name_span }); } - Ok(Expr::StateObject(fields)) + Ok(Expr::new(ExprKind::StateObject(fields), span)) } -fn parse_literal(pair: Pair<'_, Rule>) -> Result { +fn parse_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { match pair.as_rule() { - Rule::BooleanLiteral => Ok(Expr::Bool(pair.as_str() == "true")), + Rule::BooleanLiteral => Ok(Expr::new(ExprKind::Bool(pair.as_str() == "true"), Span::from(pair.as_span()))), Rule::number_literal => parse_number_literal(pair), - Rule::NumberLiteral => parse_number(pair.as_str()), - Rule::HexLiteral => parse_hex_literal(pair.as_str()), + Rule::NumberLiteral => parse_number_expr(pair), + Rule::HexLiteral => parse_hex_literal(pair), Rule::StringLiteral => parse_string_literal(pair), Rule::DateLiteral => parse_date_literal(pair), _ => Err(CompilerError::Unsupported(format!("literal not supported: {:?}", pair.as_rule()))), } } -fn parse_number(raw: &str) -> Result { - let cleaned = raw.replace('_', ""); - if let Some((base_str, exp_str)) = cleaned.split_once('e').or_else(|| cleaned.split_once('E')) { - if exp_str.is_empty() { - return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); - } - let base: i64 = base_str.parse().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - let exp: i64 = exp_str.parse().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - if exp < 0 { - return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); - } - let pow = 10i128.pow(exp as u32); - let value = - (base as i128).checked_mul(pow).ok_or_else(|| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - if value > i64::MAX as i128 || value < i64::MIN as i128 { - return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); - } - return Ok(Expr::Int(value as i64)); +fn parse_number_expr<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let value = parse_number(pair.as_str())?; + Ok(Expr::new(ExprKind::Int(value), span)) +} + +fn parse_number(raw: &str) -> Result { + let raw = raw.trim(); + let mut parts = raw.split(['e', 'E']); + let base_raw = parts.next().unwrap_or(""); + let exp_raw = parts.next(); + + // nothing allowed after having the exponent + if parts.next().is_some() { + return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); } - let value: i64 = cleaned.parse().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - Ok(Expr::Int(value)) + + let base_clean = base_raw.replace('_', ""); + if base_clean.is_empty() || base_clean == "-" { + return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); + } + let mut value = + base_clean.parse::().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; + + if let Some(exp_raw) = exp_raw { + let exp_clean = exp_raw.replace('_', ""); + + // rejects negative exponent + let exp = exp_clean.parse::().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; + let pow = 10i128.checked_pow(exp).ok_or_else(|| CompilerError::InvalidLiteral(format!("number literal overflow '{raw}'")))?; + value = value.checked_mul(pow).ok_or_else(|| CompilerError::InvalidLiteral(format!("number literal overflow '{raw}'")))?; + } + + if value < i64::MIN as i128 || value > i64::MAX as i128 { + return Err(CompilerError::InvalidLiteral(format!("number literal overflow '{raw}'"))); + } + + Ok(value as i64) } -fn parse_array(pair: Pair<'_, Rule>) -> Result { +fn parse_array<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut values = Vec::new(); for expr_pair in pair.into_inner() { values.push(parse_expression(expr_pair)?); } - Ok(Expr::Array(values)) + Ok(Expr::new(ExprKind::Array(values), span)) } -fn parse_function_call(pair: Pair<'_, Rule>) -> Result { +fn parse_function_call_parts<'i>(pair: Pair<'i, Rule>) -> Result<(Identifier<'i>, Vec>), CompilerError> { let mut inner = pair.into_inner(); - let name = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?.as_str().to_string(); + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?; let args = match inner.next() { Some(list) => parse_expression_list(list)?, None => Vec::new(), }; - Ok(Expr::Call { name, args }) + let name = parse_identifier(name_pair)?; + Ok((name, args)) +} + +fn parse_function_call<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let (Identifier { name, span: name_span }, args) = parse_function_call_parts(pair)?; + Ok(Expr::new(ExprKind::Call { name, args, name_span }, span)) } -fn parse_instantiation(pair: Pair<'_, Rule>) -> Result { +fn parse_instantiation<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); - let name = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constructor name".to_string()))?.as_str().to_string(); + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constructor name".to_string()))?; let args = match inner.next() { Some(list) => parse_expression_list(list)?, None => Vec::new(), }; - Ok(Expr::New { name, args }) + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + Ok(Expr::new(ExprKind::New { name, args, name_span }, span)) } -fn parse_expression_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_expression_list<'i>(pair: Pair<'i, Rule>) -> Result>, CompilerError> { let mut args = Vec::new(); for expr_pair in pair.into_inner() { args.push(parse_expression(expr_pair)?); @@ -920,56 +1375,64 @@ fn parse_expression_list(pair: Pair<'_, Rule>) -> Result, CompilerErro Ok(args) } -fn parse_cast(pair: Pair<'_, Rule>) -> Result { +fn parse_cast<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); - let type_name = inner.next().ok_or_else(|| CompilerError::Unsupported("missing cast type".to_string()))?.as_str().to_string(); - let args = match inner.next() { - Some(list) => parse_expression_list(list)?, - None => Vec::new(), - }; + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing cast type".to_string()))?; + let type_name = type_pair.as_str().trim().to_string(); + let type_span = Span::from(type_pair.as_span()); + + let mut args = Vec::new(); + for part in inner { + args.push(parse_expression(part)?); + } + if type_name == "bytes" { - return Ok(Expr::Call { name: "bytes".to_string(), args }); + return Ok(Expr::new(ExprKind::Call { name: "bytes".to_string(), args, name_span: type_span }, span)); } + if type_name == "byte" { - return Ok(Expr::Call { name: "byte[1]".to_string(), args }); + return Ok(Expr::new(ExprKind::Call { name: "byte[1]".to_string(), args, name_span: type_span }, span)); } + if type_name == "int" { - return Ok(Expr::Call { name: "int".to_string(), args }); + return Ok(Expr::new(ExprKind::Call { name: "int".to_string(), args, name_span: type_span }, span)); } + if matches!(type_name.as_str(), "sig" | "pubkey" | "datasig") { - return Ok(Expr::Call { name: type_name, args }); + return Ok(Expr::new(ExprKind::Call { name: type_name, args, name_span: type_span }, span)); } + // Handle single byte cast (duplicate check removed above) // Support type[N] syntax if let Some(bracket_pos) = type_name.find('[') { if type_name.ends_with(']') { - let _base_type = &type_name[..bracket_pos]; let size_str = &type_name[bracket_pos + 1..type_name.len() - 1]; - // Support both type[N] and type[] (dynamic array) - if size_str.is_empty() { - // Dynamic array cast like byte[] - return Ok(Expr::Call { name: type_name.to_string(), args }); - } else if let Ok(_size) = size_str.parse::() { - // Fixed-size array cast like byte[32] - return Ok(Expr::Call { name: type_name.to_string(), args }); + if size_str.is_empty() || size_str.parse::().is_ok() { + return Ok(Expr::new(ExprKind::Call { name: type_name, args, name_span: type_span }, span)); } } } + Err(CompilerError::Unsupported(format!("cast type not supported: {type_name}"))) } -fn parse_number_literal(pair: Pair<'_, Rule>) -> Result { +fn parse_number_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); let number = inner.next().ok_or_else(|| CompilerError::InvalidLiteral("missing number literal".to_string()))?; let value = parse_number(number.as_str())?; - if let Some(unit_pair) = inner.next() { - let unit = unit_pair.as_str(); - return apply_number_unit(value, unit); + let expr = Expr::new(ExprKind::Int(value), span); + if let Some(unit) = inner.next() { + return apply_number_unit(expr, unit.as_str()); } - Ok(value) + Ok(expr) } -fn parse_hex_literal(raw: &str) -> Result { +fn parse_hex_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let raw = pair.as_str(); let trimmed = raw.trim_start_matches("0x").trim_start_matches("0X"); let normalized = if trimmed.len() % 2 != 0 { format!("0{trimmed}") } else { trimmed.to_string() }; let bytes = (0..normalized.len()) @@ -977,13 +1440,13 @@ fn parse_hex_literal(raw: &str) -> Result { .map(|i| u8::from_str_radix(&normalized[i..i + 2], 16)) .collect::, _>>() .map_err(|_| CompilerError::InvalidLiteral(format!("invalid hex literal '{raw}'")))?; - // Convert Vec to Expr::Array of Expr::Byte - Ok(Expr::Array(bytes.into_iter().map(Expr::Byte).collect())) + Ok(Expr::new(ExprKind::Array(bytes.into_iter().map(|byte| Expr::new(ExprKind::Byte(byte), span)).collect()), span)) } -fn apply_number_unit(expr: Expr, unit: &str) -> Result { - let value = match expr { - Expr::Int(value) => value, +fn apply_number_unit<'i>(expr: Expr<'i>, unit: &str) -> Result, CompilerError> { + let span = expr.span; + let value = match expr.kind { + ExprKind::Int(value) => value, _ => return Err(CompilerError::InvalidLiteral("number literal is not an int".to_string())), }; let multiplier = match unit { @@ -997,41 +1460,37 @@ fn apply_number_unit(expr: Expr, unit: &str) -> Result { "kas" => 100_000_000, _ => return Err(CompilerError::Unsupported(format!("number unit '{unit}' not supported"))), }; - Ok(Expr::Int(value.saturating_mul(multiplier))) + Ok(Expr::new(ExprKind::Int(value.saturating_mul(multiplier)), span)) } -fn parse_date_literal(pair: Pair<'_, Rule>) -> Result { - let raw = pair.as_str(); - let start = raw - .find('"') - .or_else(|| raw.find('\'')) - .ok_or_else(|| CompilerError::InvalidLiteral("date literal missing quotes".to_string()))?; - let quote = raw.as_bytes()[start] as char; - let end = raw[start + 1..] - .find(quote) - .map(|idx| idx + start + 1) - .ok_or_else(|| CompilerError::InvalidLiteral("date literal missing closing quote".to_string()))?; - let value = &raw[start + 1..end]; - - let timestamp = NaiveDateTime::parse_from_str(value, "%Y-%m-%dT%H:%M:%S") - .map_err(|_| CompilerError::InvalidLiteral("invalid date literal".to_string()))? +fn parse_date_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + let string_pair = inner.next().ok_or_else(|| CompilerError::InvalidLiteral("missing date literal".to_string()))?; + let value = match parse_string_literal(string_pair)? { + Expr { kind: ExprKind::String(value), .. } => value, + _ => return Err(CompilerError::InvalidLiteral("invalid date literal".to_string())), + }; + let timestamp = NaiveDateTime::parse_from_str(&value, "%Y-%m-%dT%H:%M:%S") + .map_err(|_| CompilerError::InvalidLiteral(format!("invalid date literal '{value}'")))? .and_utc() .timestamp(); - Ok(Expr::Int(timestamp)) + Ok(Expr::new(ExprKind::DateLiteral(timestamp), span)) } -fn parse_string_literal(pair: Pair<'_, Rule>) -> Result { +fn parse_string_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let raw = pair.as_str(); - let unquoted = if raw.starts_with('"') && raw.ends_with('"') || raw.starts_with('\'') && raw.ends_with('\'') { + let unquoted = if (raw.starts_with('"') && raw.ends_with('"')) || (raw.starts_with('\'') && raw.ends_with('\'')) { &raw[1..raw.len() - 1] } else { raw }; let unescaped = unquoted.replace("\\\"", "\"").replace("\\'", "'"); - Ok(Expr::String(unescaped)) + Ok(Expr::new(ExprKind::String(unescaped), span)) } -fn parse_nullary(raw: &str) -> Result { +fn parse_nullary<'i>(raw: &str, span: Span<'i>) -> Result, CompilerError> { let op = match raw { "this.activeInputIndex" => NullaryOp::ActiveInputIndex, "this.activeScriptPubKey" => NullaryOp::ActiveScriptPubKey, @@ -1043,45 +1502,49 @@ fn parse_nullary(raw: &str) -> Result { "tx.locktime" => NullaryOp::TxLockTime, _ => return Err(CompilerError::Unsupported(format!("unknown nullary op: {raw}"))), }; - Ok(Expr::Nullary(op)) + Ok(Expr::new(ExprKind::Nullary(op), span)) } -fn parse_introspection(pair: Pair<'_, Rule>) -> Result { +fn parse_introspection<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let text = pair.as_str(); let mut inner = pair.into_inner(); let index_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing introspection index".to_string()))?; let field_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing introspection field".to_string()))?; let index = Box::new(parse_expression(index_pair)?); - let field = field_pair.as_str(); - + let field_raw = field_pair.as_str(); let kind = if text.starts_with("tx.inputs") { - match field { + match field_raw { ".value" => IntrospectionKind::InputValue, ".scriptPubKey" => IntrospectionKind::InputScriptPubKey, ".sigScript" => IntrospectionKind::InputSigScript, - _ => return Err(CompilerError::Unsupported(format!("input field '{field}' not supported"))), + // TODO: support this + ".outpointTransactionHash" => IntrospectionKind::InputOutpointTransactionHash, + ".outpointIndex" => IntrospectionKind::InputOutpointIndex, + ".sequenceNumber" => IntrospectionKind::InputSequenceNumber, + _ => return Err(CompilerError::Unsupported(format!("input field '{field_raw}' not supported"))), } } else if text.starts_with("tx.outputs") { - match field { + match field_raw { ".value" => IntrospectionKind::OutputValue, ".scriptPubKey" => IntrospectionKind::OutputScriptPubKey, - _ => return Err(CompilerError::Unsupported(format!("output field '{field}' not supported"))), + _ => return Err(CompilerError::Unsupported(format!("output field '{field_raw}' not supported"))), } } else { return Err(CompilerError::Unsupported("unknown introspection root".to_string())); }; - Ok(Expr::Introspection { kind, index }) + Ok(Expr::new(ExprKind::Introspection { kind, index, field_span: Span::from(field_pair.as_span()) }, span)) } fn single_inner(pair: Pair<'_, Rule>) -> Result, CompilerError> { pair.into_inner().next().ok_or_else(|| CompilerError::Unsupported("expected inner pair".to_string())) } -fn parse_infix(pair: Pair<'_, Rule>, mut parse_operand: F, mut map_op: G) -> Result +fn parse_infix<'i, F, G>(pair: Pair<'i, Rule>, mut parse_operand: F, mut map_op: G) -> Result, CompilerError> where - F: FnMut(Pair<'_, Rule>) -> Result, + F: FnMut(Pair<'i, Rule>) -> Result, CompilerError>, G: FnMut(Pair<'_, Rule>) -> Result, { let mut inner = pair.into_inner(); @@ -1092,7 +1555,8 @@ where let rhs = inner.next().ok_or_else(|| CompilerError::Unsupported("missing infix rhs".to_string()))?; let op = map_op(op_pair)?; let rhs_expr = parse_operand(rhs)?; - expr = Expr::Binary { op, left: Box::new(expr), right: Box::new(rhs_expr) }; + let span = expr.span.join(&rhs_expr.span); + expr = Expr::new(ExprKind::Binary { op, left: Box::new(expr), right: Box::new(rhs_expr) }, span); } Ok(expr) @@ -1179,3 +1643,15 @@ fn map_factor(pair: Pair<'_, Rule>) -> Result { _ => Err(CompilerError::Unsupported("unexpected factor operator".to_string())), } } + +// validate user input +fn parse_identifier<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let value = pair.as_str().to_string(); + + if value.starts_with("__") { + return Err(CompilerError::Unsupported("identifiers starting with '__' are reserved".to_string())); + } + + Ok(Identifier { name: value, span }) +} diff --git a/silverscript-lang/src/bin/sil-debug.rs b/silverscript-lang/src/bin/sil-debug.rs index b13531cb..8fcd602f 100644 --- a/silverscript-lang/src/bin/sil-debug.rs +++ b/silverscript-lang/src/bin/sil-debug.rs @@ -6,9 +6,10 @@ use kaspa_consensus_core::hashing::sighash::SigHashReusedValuesUnsync; use kaspa_txscript::caches::Cache; use kaspa_txscript::{EngineCtx, EngineFlags}; -use silverscript_lang::ast::{Expr, parse_contract_ast}; +use silverscript_lang::ast::{Expr, ExprKind, parse_contract_ast}; use silverscript_lang::compiler::{CompileOptions, compile_contract}; use silverscript_lang::debug::session::{DebugEngine, DebugSession}; +use silverscript_lang::span; const PROMPT: &str = "(sdb) "; @@ -47,11 +48,11 @@ fn parse_hex_bytes(raw: &str) -> Result, Box> { Ok(out) } -fn bytes_expr(bytes: Vec) -> Expr { - Expr::Array(bytes.into_iter().map(Expr::Byte).collect()) +fn bytes_expr(bytes: Vec) -> Expr<'static> { + Expr::new(ExprKind::Array(bytes.into_iter().map(Expr::byte).collect()), span::Span::default()) } -fn parse_typed_arg(type_name: &str, raw: &str) -> Result> { +fn parse_typed_arg(type_name: &str, raw: &str) -> Result, Box> { if let Some(element_type) = type_name.strip_suffix("[]") { let trimmed = raw.trim(); if trimmed.starts_with('[') { @@ -59,14 +60,14 @@ fn parse_typed_arg(type_name: &str, raw: &str) -> Result Expr::Int(n.as_i64().ok_or("invalid int in array")?), - serde_json::Value::Bool(b) => Expr::Bool(b), + serde_json::Value::Number(n) => Expr::int(n.as_i64().ok_or("invalid int in array")?), + serde_json::Value::Bool(b) => Expr::bool(b), serde_json::Value::String(s) => parse_typed_arg(element_type, &s)?, _ => return Err("unsupported array element (expected number/bool/string)".into()), }; out.push(expr); } - return Ok(Expr::Array(out)); + return Ok(Expr::new(ExprKind::Array(out), span::Span::default())); } if element_type == "byte" { return Ok(bytes_expr(parse_hex_bytes(trimmed)?)); @@ -75,16 +76,16 @@ fn parse_typed_arg(type_name: &str, raw: &str) -> Result Ok(Expr::Int(parse_int_arg(raw)?)), + "int" => Ok(Expr::int(parse_int_arg(raw)?)), "bool" => match raw { - "true" => Ok(Expr::Bool(true)), - "false" => Ok(Expr::Bool(false)), + "true" => Ok(Expr::bool(true)), + "false" => Ok(Expr::bool(false)), _ => Err(format!("invalid bool '{raw}' (expected true/false)").into()), }, - "string" => Ok(Expr::String(raw.to_string())), + "string" => Ok(Expr::string(raw.to_string())), "byte" => { let bytes = parse_hex_bytes(raw)?; - if bytes.len() == 1 { Ok(Expr::Byte(bytes[0])) } else { Err(format!("byte expects 1 byte, got {}", bytes.len()).into()) } + if bytes.len() == 1 { Ok(Expr::byte(bytes[0])) } else { Err(format!("byte expects 1 byte, got {}", bytes.len()).into()) } } "bytes" => Ok(bytes_expr(parse_hex_bytes(raw)?)), "pubkey" => { @@ -126,7 +127,7 @@ fn parse_typed_arg(type_name: &str, raw: &str) -> Result) { +fn show_stack(session: &DebugSession<'_, '_>) { println!("Stack:"); let stack = session.stack(); for (i, item) in stack.iter().enumerate().rev() { @@ -134,7 +135,7 @@ fn show_stack(session: &DebugSession<'_>) { } } -fn show_source_context(session: &DebugSession<'_>) { +fn show_source_context(session: &DebugSession<'_, '_>) { let Some(context) = session.source_context() else { println!("No source context available."); return; @@ -146,7 +147,7 @@ fn show_source_context(session: &DebugSession<'_>) { } } -fn show_vars(session: &DebugSession<'_>) { +fn show_vars(session: &DebugSession<'_, '_>) { match session.list_variables() { Ok(variables) => { if variables.is_empty() { @@ -168,12 +169,12 @@ fn show_vars(session: &DebugSession<'_>) { } } -fn show_step_view(session: &DebugSession<'_>) { +fn show_step_view(session: &DebugSession<'_, '_>) { show_source_context(session); show_vars(session); } -fn run_repl(session: &mut DebugSession<'_>) -> Result<(), kaspa_txscript_errors::TxScriptError> { +fn run_repl(session: &mut DebugSession<'_, '_>) -> Result<(), kaspa_txscript_errors::TxScriptError> { let stdin = io::stdin(); loop { print!("{PROMPT}"); diff --git a/silverscript-lang/src/bin/silverc.rs b/silverscript-lang/src/bin/silverc.rs index fbd89538..557988c0 100644 --- a/silverscript-lang/src/bin/silverc.rs +++ b/silverscript-lang/src/bin/silverc.rs @@ -1,10 +1,44 @@ -use std::env; use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; -use silverscript_lang::ast::Expr; +use clap::Parser; +use silverscript_lang::ast::{Expr, parse_contract_ast}; use silverscript_lang::compiler::{CompileOptions, compile_contract}; +#[derive(Debug, Parser)] +#[command( + name = "silverc", + about = "Compile SilverScript contracts into JSON artifacts", + long_about = "Compile a SilverScript source file into a compiled JSON artifact, or parse only and emit AST JSON.\n\ +\n\ +Destination precedence:\n\ +1) -c, --stdout -> write JSON to stdout\n\ +2) -o -> write JSON to the specified file\n\ +3) compile default -> .json", + after_help = "Examples:\n\ + silverc contract.sil\n\ + silverc contract.sil -o artifact.json\n\ + silverc contract.sil -c", + next_line_help = true +)] +struct Cli { + /// Source SilverScript file (e.g. contract.sil) + #[arg(value_name = "SOURCE.sil")] + src: PathBuf, + /// Path to JSON constructor arguments + #[arg(visible_alias = "ctor", long = "constructor-args", value_name = "CTOR.json")] + constructor_args: Option, + /// Output file path for JSON output + #[arg(short = 'o', long = "output", value_name = "FILE.json")] + out: Option, + /// Write JSON output to stdout + #[arg(short = 'c', long = "stdout")] + stdout: bool, + /// Parse source and emit AST JSON without compiling + #[arg(long = "ast-only")] + ast_only: bool, +} + fn main() { if let Err(err) = run() { eprintln!("{err}"); @@ -13,47 +47,29 @@ fn main() { } fn run() -> Result<(), String> { - let args = env::args().skip(1).collect::>(); - if args.is_empty() { - return Err("usage: silverc [--constructor-args ctor.json] [-o dst.json]".to_string()); - } + let cli = match Cli::try_parse() { + Ok(cli) => cli, + Err(err) if err.use_stderr() => return Err(err.to_string()), + Err(err) => { + err.print().map_err(|print_err| format!("failed to print clap output: {print_err}"))?; + return Ok(()); + } + }; - let mut src: Option = None; - let mut ctor_args_path: Option = None; - let mut out_path: Option = None; + let source = fs::read_to_string(&cli.src).map_err(|err| format!("failed to read {}: {err}", cli.src.display()))?; - let mut i = 0; - while i < args.len() { - match args[i].as_str() { - "--constructor-args" => { - let value = args.get(i + 1).ok_or_else(|| "--constructor-args requires a path".to_string())?; - ctor_args_path = Some(value.clone()); - i += 2; - } - "-o" => { - let value = args.get(i + 1).ok_or_else(|| "-o requires a path".to_string())?; - out_path = Some(value.clone()); - i += 2; - } - value if value.starts_with('-') => { - return Err(format!("unknown option: {value}")); - } - value => { - if src.is_some() { - return Err("only one source file is supported".to_string()); - } - src = Some(value.to_string()); - i += 1; - } - } + if cli.ast_only { + let ast = parse_contract_ast(&source).map_err(|err| format!("parse error: {err}"))?; + let rendered = ast.to_string(); + let target = resolve_output_target(&cli, &cli.src, true); + emit_output(&rendered, target)?; + return Ok(()); } - let src = src.ok_or_else(|| "missing source file".to_string())?; - let source = fs::read_to_string(&src).map_err(|err| format!("failed to read {src}: {err}"))?; - - let constructor_args = if let Some(path) = ctor_args_path { - let json = fs::read_to_string(&path).map_err(|err| format!("failed to read {path}: {err}"))?; - serde_json::from_str::>(&json).map_err(|err| format!("failed to parse constructor args {path}: {err}"))? + let constructor_args = if let Some(path) = &cli.constructor_args { + let json = fs::read_to_string(path).map_err(|err| format!("failed to read {}: {err}", path.display()))?; + serde_json::from_str::>(&json) + .map_err(|err| format!("failed to parse constructor args {}: {err}", path.display()))? } else { Vec::new() }; @@ -61,21 +77,43 @@ fn run() -> Result<(), String> { let compiled = compile_contract(&source, &constructor_args, CompileOptions::default()).map_err(|err| format!("compile error: {err}"))?; - let output_path = match out_path { - Some(path) => PathBuf::from(path), - None => default_output_path(&src), - }; - let json = serde_json::to_string_pretty(&compiled).map_err(|err| format!("failed to serialize output: {err}"))?; - fs::write(&output_path, json).map_err(|err| format!("failed to write {}: {err}", output_path.display()))?; + let target = resolve_output_target(&cli, &cli.src, false); + emit_output(&json, target)?; Ok(()) } -fn default_output_path(src: &str) -> PathBuf { - if let Some(stripped) = src.strip_suffix(".sil") { - PathBuf::from(format!("{stripped}.json")) - } else { - PathBuf::from(format!("{src}.json")) +enum OutputTarget { + Stdout, + File(PathBuf), +} + +fn resolve_output_target(cli: &Cli, src: &Path, ast_only: bool) -> OutputTarget { + if cli.stdout { + return OutputTarget::Stdout; + } + if let Some(path) = &cli.out { + return OutputTarget::File(path.clone()); + } + if ast_only { OutputTarget::Stdout } else { OutputTarget::File(default_output_path(src)) } +} + +fn emit_output(content: &str, target: OutputTarget) -> Result<(), String> { + match target { + OutputTarget::Stdout => { + println!("{content}"); + Ok(()) + } + OutputTarget::File(path) => { + fs::write(&path, content).map_err(|err| format!("failed to write {}: {err}", path.display()))?; + Ok(()) + } } } + +fn default_output_path(src: &Path) -> PathBuf { + let mut output_path = src.to_path_buf(); + output_path.set_extension("json"); + output_path +} diff --git a/silverscript-lang/src/compiler.rs b/silverscript-lang/src/compiler.rs index 6f6c3a86..9b47b384 100644 --- a/silverscript-lang/src/compiler.rs +++ b/silverscript-lang/src/compiler.rs @@ -1,39 +1,23 @@ use std::collections::{HashMap, HashSet}; use kaspa_txscript::opcodes::codes::*; -use kaspa_txscript::script_builder::{ScriptBuilder, ScriptBuilderError}; +use kaspa_txscript::script_builder::ScriptBuilder; use serde::{Deserialize, Serialize}; -use thiserror::Error; use crate::ast::{ - ArrayDim, BinaryOp, ContractAst, ContractFieldAst, Expr, FunctionAst, IntrospectionKind, NullaryOp, SplitPart, StateBindingAst, - Statement, StatementKind, TimeVar, TypeBase, TypeRef, UnaryOp, parse_contract_ast, parse_type_ref, + ArrayDim, BinaryOp, ContractAst, ContractFieldAst, Expr, ExprKind, FunctionAst, IntrospectionKind, NullaryOp, SplitPart, + StateBindingAst, StateFieldExpr, Statement, TimeVar, TypeBase, TypeRef, UnaryOp, UnarySuffixKind, parse_contract_ast, + parse_type_ref, }; +pub use crate::errors::{CompilerError, ErrorSpan}; use crate::debug::labels::synthetic; use crate::debug::{DebugInfo, SourceSpan}; -use crate::parser::Rule; -use chrono::NaiveDateTime; +use crate::span; mod debug_recording; use debug_recording::{DebugSink, FunctionDebugRecorder, record_synthetic_range}; -#[derive(Debug, Error)] -pub enum CompilerError { - #[error("parse error: {0}")] - Parse(#[from] pest::error::Error), - #[error("unsupported feature: {0}")] - Unsupported(String), - #[error("invalid literal: {0}")] - InvalidLiteral(String), - #[error("undefined identifier: {0}")] - UndefinedIdentifier(String), - #[error("cyclic identifier reference: {0}")] - CyclicIdentifier(String), - #[error("script build error: {0}")] - ScriptBuild(#[from] ScriptBuilderError), -} - #[derive(Debug, Clone, Copy, Default)] pub struct CompileOptions { pub allow_yield: bool, @@ -53,42 +37,44 @@ pub struct FunctionAbiEntry { pub inputs: Vec, } -pub type FunctionAbi = Vec; - #[derive(Debug, Serialize, Deserialize)] -pub struct CompiledContract { +pub struct CompiledContract<'i> { pub contract_name: String, pub script: Vec, - pub ast: ContractAst, - pub abi: FunctionAbi, + pub ast: ContractAst<'i>, + pub abi: Vec, pub without_selector: bool, - pub debug_info: Option, + pub debug_info: Option>, } -pub fn compile_contract(source: &str, constructor_args: &[Expr], options: CompileOptions) -> Result { +pub fn compile_contract<'i>( + source: &'i str, + constructor_args: &[Expr<'i>], + options: CompileOptions, +) -> Result, CompilerError> { let contract = parse_contract_ast(source)?; compile_contract_impl(&contract, constructor_args, options, Some(source)) } -pub fn compile_contract_ast( - contract: &ContractAst, - constructor_args: &[Expr], +pub fn compile_contract_ast<'i>( + contract: &ContractAst<'i>, + constructor_args: &[Expr<'i>], options: CompileOptions, -) -> Result { +) -> Result, CompilerError> { compile_contract_impl(contract, constructor_args, options, None) } -fn compile_contract_impl( - contract: &ContractAst, - constructor_args: &[Expr], +fn compile_contract_impl<'i>( + contract: &ContractAst<'i>, + constructor_args: &[Expr<'i>], options: CompileOptions, - source: Option<&str>, -) -> Result { + source: Option<&'i str>, +) -> Result, CompilerError> { if contract.functions.is_empty() { return Err(CompilerError::Unsupported("contract has no functions".to_string())); } - let entrypoint_functions: Vec<&FunctionAst> = contract.functions.iter().filter(|func| func.entrypoint).collect(); + let entrypoint_functions: Vec<&FunctionAst<'i>> = contract.functions.iter().filter(|func| func.entrypoint).collect(); if entrypoint_functions.is_empty() { return Err(CompilerError::Unsupported("contract has no entrypoint functions".to_string())); } @@ -106,7 +92,8 @@ fn compile_contract_impl( let without_selector = entrypoint_functions.len() == 1; - let mut constants = contract.constants.clone(); + let mut constants: HashMap> = + contract.constants.iter().map(|constant| (constant.name.clone(), constant.expr.clone())).collect(); for (param, value) in contract.params.iter().zip(constructor_args.iter()) { constants.insert(param.name.clone(), value.clone()); } @@ -114,7 +101,7 @@ fn compile_contract_impl( let functions_map = contract.functions.iter().cloned().map(|func| (func.name.clone(), func)).collect::>(); let function_order = contract.functions.iter().enumerate().map(|(index, func)| (func.name.clone(), index)).collect::>(); - let abi = build_function_abi(contract); + let function_abi_entries = build_function_abi_entries(contract); let uses_script_size = contract_uses_script_size(contract); let mut script_size = if uses_script_size { Some(100i64) } else { None }; @@ -191,7 +178,7 @@ fn compile_contract_impl( contract_name: contract.name.clone(), script, ast: contract.clone(), - abi, + abi: function_abi_entries, without_selector, debug_info, }); @@ -204,7 +191,7 @@ fn compile_contract_impl( contract_name: contract.name.clone(), script, ast: contract.clone(), - abi, + abi: function_abi_entries, without_selector, debug_info, }); @@ -215,8 +202,8 @@ fn compile_contract_impl( Err(CompilerError::Unsupported("script size did not stabilize".to_string())) } -fn contract_uses_script_size(contract: &ContractAst) -> bool { - if contract.constants.values().any(expr_uses_script_size) { +fn contract_uses_script_size<'i>(contract: &ContractAst<'i>) -> bool { + if contract.constants.iter().any(|constant| expr_uses_script_size(&constant.expr)) { return true; } if contract.fields.iter().any(|field| expr_uses_script_size(&field.expr)) { @@ -225,12 +212,12 @@ fn contract_uses_script_size(contract: &ContractAst) -> bool { contract.functions.iter().any(|func| func.body.iter().any(statement_uses_script_size)) } -fn compile_contract_fields( - fields: &[ContractFieldAst], - base_constants: &HashMap, +fn compile_contract_fields<'i>( + fields: &[ContractFieldAst<'i>], + base_constants: &HashMap>, options: CompileOptions, script_size: Option, -) -> Result<(HashMap, Vec), CompilerError> { +) -> Result<(HashMap>, Vec), CompilerError> { let mut env = base_constants.clone(); let mut field_values = HashMap::new(); let mut field_types = HashMap::new(); @@ -256,7 +243,7 @@ fn compile_contract_fields( let mut compile_visiting = HashSet::new(); let mut stack_depth = 0i64; if field.type_ref.array_dims.is_empty() && field.type_ref.base == TypeBase::Int { - let Expr::Int(value) = resolved else { + let ExprKind::Int(value) = &resolved.kind else { return Err(CompilerError::Unsupported(format!("contract field '{}' expects compile-time int value", field.name))); }; builder.add_data(&value.to_le_bytes())?; @@ -284,110 +271,109 @@ fn compile_contract_fields( Ok((field_values, builder.drain())) } -fn statement_uses_script_size(stmt: &Statement) -> bool { - match &stmt.kind { - StatementKind::VariableDefinition { expr, .. } => expr.as_ref().is_some_and(expr_uses_script_size), - StatementKind::TupleAssignment { expr, .. } => expr_uses_script_size(expr), - StatementKind::ArrayPush { expr, .. } => expr_uses_script_size(expr), - StatementKind::FunctionCall { name, args } => name == "validateOutputState" || args.iter().any(expr_uses_script_size), - StatementKind::FunctionCallAssign { args, .. } => args.iter().any(expr_uses_script_size), - StatementKind::StateFunctionCallAssign { name, args, .. } => { - name == "readInputState" || args.iter().any(expr_uses_script_size) - } - StatementKind::Assign { expr, .. } => expr_uses_script_size(expr), - StatementKind::TimeOp { expr, .. } => expr_uses_script_size(expr), - StatementKind::Require { expr, .. } => expr_uses_script_size(expr), - StatementKind::If { condition, then_branch, else_branch } => { +fn statement_uses_script_size(stmt: &Statement<'_>) -> bool { + match stmt { + Statement::VariableDefinition { expr, .. } => expr.as_ref().is_some_and(expr_uses_script_size), + Statement::TupleAssignment { expr, .. } => expr_uses_script_size(expr), + Statement::ArrayPush { expr, .. } => expr_uses_script_size(expr), + Statement::FunctionCall { name, args, .. } => name == "validateOutputState" || args.iter().any(expr_uses_script_size), + Statement::FunctionCallAssign { args, .. } => args.iter().any(expr_uses_script_size), + Statement::StateFunctionCallAssign { name, args, .. } => name == "readInputState" || args.iter().any(expr_uses_script_size), + Statement::Assign { expr, .. } => expr_uses_script_size(expr), + Statement::TimeOp { expr, .. } => expr_uses_script_size(expr), + Statement::Require { expr, .. } => expr_uses_script_size(expr), + Statement::If { condition, then_branch, else_branch, .. } => { expr_uses_script_size(condition) || then_branch.iter().any(statement_uses_script_size) || else_branch.as_ref().is_some_and(|branch| branch.iter().any(statement_uses_script_size)) } - StatementKind::For { start, end, body, .. } => { + Statement::For { start, end, body, .. } => { expr_uses_script_size(start) || expr_uses_script_size(end) || body.iter().any(statement_uses_script_size) } - StatementKind::Yield { expr } => expr_uses_script_size(expr), - StatementKind::Return { exprs } => exprs.iter().any(expr_uses_script_size), - StatementKind::Console { args } => args.iter().any(|arg| match arg { - crate::ast::ConsoleArg::Identifier(_) => false, + Statement::Yield { expr, .. } => expr_uses_script_size(expr), + Statement::Return { exprs, .. } => exprs.iter().any(expr_uses_script_size), + Statement::Console { args, .. } => args.iter().any(|arg| match arg { + crate::ast::ConsoleArg::Identifier(_, _) => false, crate::ast::ConsoleArg::Literal(expr) => expr_uses_script_size(expr), }), } } -fn expr_uses_script_size(expr: &Expr) -> bool { - match expr { - Expr::Nullary(NullaryOp::ThisScriptSize) => true, - Expr::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, - Expr::Unary { expr, .. } => expr_uses_script_size(expr), - Expr::Binary { left, right, .. } => expr_uses_script_size(left) || expr_uses_script_size(right), - Expr::IfElse { condition, then_expr, else_expr } => { +fn expr_uses_script_size<'i>(expr: &Expr<'i>) -> bool { + match &expr.kind { + ExprKind::Nullary(NullaryOp::ThisScriptSize) => true, + ExprKind::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, + ExprKind::Unary { expr, .. } => expr_uses_script_size(expr), + ExprKind::Binary { left, right, .. } => expr_uses_script_size(left) || expr_uses_script_size(right), + ExprKind::IfElse { condition, then_expr, else_expr } => { expr_uses_script_size(condition) || expr_uses_script_size(then_expr) || expr_uses_script_size(else_expr) } - Expr::Array(values) => values.iter().any(expr_uses_script_size), - Expr::StateObject(fields) => fields.iter().any(|field| expr_uses_script_size(&field.expr)), - Expr::Call { args, .. } => args.iter().any(expr_uses_script_size), - Expr::New { args, .. } => args.iter().any(expr_uses_script_size), - Expr::Split { source, index, .. } => expr_uses_script_size(source) || expr_uses_script_size(index), - Expr::Slice { source, start, end } => { + ExprKind::Array(values) => values.iter().any(expr_uses_script_size), + ExprKind::StateObject(fields) => fields.iter().any(|field| expr_uses_script_size(&field.expr)), + ExprKind::Call { args, .. } => args.iter().any(expr_uses_script_size), + ExprKind::New { args, .. } => args.iter().any(expr_uses_script_size), + ExprKind::Split { source, index, .. } => expr_uses_script_size(source) || expr_uses_script_size(index), + ExprKind::Slice { source, start, end, .. } => { expr_uses_script_size(source) || expr_uses_script_size(start) || expr_uses_script_size(end) } - Expr::ArrayIndex { source, index } => expr_uses_script_size(source) || expr_uses_script_size(index), - Expr::Introspection { index, .. } => expr_uses_script_size(index), - Expr::Int(_) | Expr::Bool(_) | Expr::Byte(_) | Expr::String(_) | Expr::Identifier(_) => false, - Expr::Nullary(_) => false, + ExprKind::UnarySuffix { source, .. } => expr_uses_script_size(source), + ExprKind::ArrayIndex { source, index } => expr_uses_script_size(source) || expr_uses_script_size(index), + ExprKind::Introspection { index, .. } => expr_uses_script_size(index), + ExprKind::Int(_) + | ExprKind::Bool(_) + | ExprKind::Byte(_) + | ExprKind::String(_) + | ExprKind::Identifier(_) + | ExprKind::DateLiteral(_) + | ExprKind::NumberWithUnit { .. } + | ExprKind::Nullary(_) => false, } } -// Helper to check if an expression is an array of bytes -fn is_byte_array(expr: &Expr) -> bool { - match expr { - Expr::Array(values) => values.iter().all(|v| matches!(v, Expr::Byte(_))), - _ => false, - } +fn is_byte_array<'i>(expr: &Expr<'i>) -> bool { + byte_array_len(expr).is_some() } -// Helper to get the length of a byte array -fn byte_array_len(expr: &Expr) -> Option { - match expr { - Expr::Array(values) if values.iter().all(|v| matches!(v, Expr::Byte(_))) => Some(values.len()), +fn byte_array_len<'i>(expr: &Expr<'i>) -> Option { + match &expr.kind { + ExprKind::Array(values) if values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))) => Some(values.len()), _ => None, } } -fn expr_matches_type_ref(expr: &Expr, type_ref: &TypeRef) -> bool { +/// Does the expression match the expected type passed as a secondary argument. +/// +/// If type is a fixed-size array (known at parsing time), it also verifies the array length. +fn expr_matches_type_ref<'i>(expr: &Expr<'i>, type_ref: &TypeRef) -> bool { if is_array_type_ref(type_ref) { - // Check for fixed-size array type[N] if let Some(size) = array_size_ref(type_ref) { - // For fixed-size arrays like byte[4], int[3] if let Some(element_type) = array_element_type_ref(type_ref) { if element_type.base == TypeBase::Byte { - // byte[N] should match Expr::Array of Expr::Byte with exact length N return byte_array_len(expr) == Some(size); } - // For other fixed-size arrays, match array literal - return matches!(expr, Expr::Array(values) if values.len() == size && array_literal_matches_type_ref(values, type_ref)); + return matches!(&expr.kind, ExprKind::Array(values) if values.len() == size && array_literal_matches_type_ref(values, type_ref)); } } - // Dynamic arrays type[] - return is_byte_array(expr) || matches!(expr, Expr::Array(values) if array_literal_matches_type_ref(values, type_ref)); + return is_byte_array(expr) + || matches!(&expr.kind, ExprKind::Array(values) if array_literal_matches_type_ref(values, type_ref)); } + match type_ref.base { - TypeBase::Int => matches!(expr, Expr::Int(_)), - TypeBase::Bool => matches!(expr, Expr::Bool(_)), - TypeBase::String => matches!(expr, Expr::String(_)), - TypeBase::Byte => matches!(expr, Expr::Byte(_)), + TypeBase::Int => matches!(&expr.kind, ExprKind::Int(_) | ExprKind::DateLiteral(_)), + TypeBase::Bool => matches!(&expr.kind, ExprKind::Bool(_)), + TypeBase::String => matches!(&expr.kind, ExprKind::String(_)), + TypeBase::Byte => matches!(&expr.kind, ExprKind::Byte(_)), TypeBase::Pubkey => byte_array_len(expr) == Some(32), TypeBase::Sig => byte_array_len(expr) == Some(65), TypeBase::Datasig => byte_array_len(expr) == Some(64), } } -fn array_literal_matches_type_ref(values: &[Expr], type_ref: &TypeRef) -> bool { +fn array_literal_matches_type_ref<'i>(values: &[Expr<'i>], type_ref: &TypeRef) -> bool { let Some(element_type) = array_element_type_ref(type_ref) else { return false; }; - // Check if this is a fixed-size array if let Some(expected_size) = array_size_ref(type_ref) { if values.len() != expected_size { return false; @@ -397,11 +383,11 @@ fn array_literal_matches_type_ref(values: &[Expr], type_ref: &TypeRef) -> bool { values.iter().all(|value| expr_matches_type_ref(value, &element_type)) } -fn array_literal_matches_type_with_env_ref( - values: &[Expr], +fn array_literal_matches_type_with_env_ref<'i>( + values: &[Expr<'i>], type_ref: &TypeRef, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { let Some(element_type) = array_element_type_ref(type_ref) else { return false; @@ -413,8 +399,8 @@ fn array_literal_matches_type_with_env_ref( } } - values.iter().all(|value| match value { - Expr::Identifier(name) => types + values.iter().all(|value| match &value.kind { + ExprKind::Identifier(name) => types .get(name) .and_then(|value_type| parse_type_ref(value_type).ok()) .is_some_and(|value_type| is_type_assignable_ref(&value_type, &element_type, constants)), @@ -422,7 +408,7 @@ fn array_literal_matches_type_with_env_ref( }) } -fn build_function_abi(contract: &ContractAst) -> FunctionAbi { +fn build_function_abi_entries<'i>(contract: &ContractAst<'i>) -> Vec { contract .functions .iter() @@ -457,11 +443,11 @@ fn array_size_ref(type_ref: &TypeRef) -> Option { } } -fn array_size_with_constants_ref(type_ref: &TypeRef, constants: &HashMap) -> Option { +fn array_size_with_constants_ref<'i>(type_ref: &TypeRef, constants: &HashMap>) -> Option { match type_ref.array_size()? { ArrayDim::Fixed(size) => Some(*size), ArrayDim::Constant(name) => { - if let Some(Expr::Int(value)) = constants.get(name) { + if let Some(Expr { kind: ExprKind::Int(value), .. }) = constants.get(name) { if *value >= 0 { return Some(*value as usize); } @@ -500,33 +486,33 @@ fn array_element_size_ref(type_ref: &TypeRef) -> Option { array_element_type_ref(type_ref).and_then(|element| fixed_type_size_ref(&element)) } -fn contains_return(stmt: &Statement) -> bool { - match &stmt.kind { - StatementKind::Return { .. } => true, - StatementKind::If { then_branch, else_branch, .. } => { +fn contains_return(stmt: &Statement<'_>) -> bool { + match stmt { + Statement::Return { .. } => true, + Statement::If { then_branch, else_branch, .. } => { then_branch.iter().any(contains_return) || else_branch.as_ref().is_some_and(|branch| branch.iter().any(contains_return)) } - StatementKind::For { body, .. } => body.iter().any(contains_return), + Statement::For { body, .. } => body.iter().any(contains_return), _ => false, } } -fn contains_yield(stmt: &Statement) -> bool { - match &stmt.kind { - StatementKind::Yield { .. } => true, - StatementKind::If { then_branch, else_branch, .. } => { +fn contains_yield(stmt: &Statement<'_>) -> bool { + match stmt { + Statement::Yield { .. } => true, + Statement::If { then_branch, else_branch, .. } => { then_branch.iter().any(contains_yield) || else_branch.as_ref().is_some_and(|branch| branch.iter().any(contains_yield)) } - StatementKind::For { body, .. } => body.iter().any(contains_yield), + Statement::For { body, .. } => body.iter().any(contains_yield), _ => false, } } -fn validate_return_types( - exprs: &[Expr], +fn validate_return_types<'i>( + exprs: &[Expr<'i>], return_types: &[TypeRef], types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> Result<(), CompilerError> { if return_types.is_empty() { return Err(CompilerError::Unsupported("return requires function return types".to_string())); @@ -547,7 +533,7 @@ fn has_explicit_array_size_ref(type_ref: &TypeRef) -> bool { !matches!(type_ref.array_size(), Some(ArrayDim::Dynamic) | None) } -fn is_array_type_assignable_ref(actual: &TypeRef, expected: &TypeRef, constants: &HashMap) -> bool { +fn is_array_type_assignable_ref<'i>(actual: &TypeRef, expected: &TypeRef, constants: &HashMap>) -> bool { if actual == expected { return true; } @@ -570,46 +556,48 @@ fn is_array_type_assignable_ref(actual: &TypeRef, expected: &TypeRef, constants: } } -fn is_type_assignable_ref(actual: &TypeRef, expected: &TypeRef, constants: &HashMap) -> bool { +fn is_type_assignable_ref<'i>(actual: &TypeRef, expected: &TypeRef, constants: &HashMap>) -> bool { actual == expected || is_array_type_assignable_ref(actual, expected, constants) } -fn expr_matches_type_with_env_ref( - expr: &Expr, +fn expr_matches_type_with_env_ref<'i>( + expr: &Expr<'i>, type_ref: &TypeRef, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { - match expr { - Expr::Identifier(name) => { + match &expr.kind { + ExprKind::Identifier(name) => { types.get(name).and_then(|t| parse_type_ref(t).ok()).is_some_and(|t| is_type_assignable_ref(&t, type_ref, constants)) } - Expr::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), + ExprKind::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), _ => expr_matches_type_ref(expr, type_ref), } } -fn expr_matches_return_type_ref( - expr: &Expr, +fn expr_matches_return_type_ref<'i>( + expr: &Expr<'i>, type_ref: &TypeRef, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { - match expr { - Expr::Identifier(name) => { + match &expr.kind { + ExprKind::Identifier(name) => { types.get(name).and_then(|t| parse_type_ref(t).ok()).is_some_and(|t| is_type_assignable_ref(&t, type_ref, constants)) } - Expr::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), - Expr::Int(_) | Expr::Bool(_) | Expr::Byte(_) | Expr::String(_) => expr_matches_type_ref(expr, type_ref), + ExprKind::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), + ExprKind::Int(_) | ExprKind::DateLiteral(_) | ExprKind::Bool(_) | ExprKind::Byte(_) | ExprKind::String(_) => { + expr_matches_type_ref(expr, type_ref) + } _ => true, } } -fn infer_fixed_array_type_from_initializer_ref( +fn infer_fixed_array_type_from_initializer_ref<'i>( declared_type: &TypeRef, - initializer: Option<&Expr>, + initializer: Option<&Expr<'i>>, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> Option { if !declared_type.array_size().is_some_and(|dim| matches!(dim, ArrayDim::Dynamic)) { return None; @@ -618,13 +606,13 @@ fn infer_fixed_array_type_from_initializer_ref( let element_type = array_element_type_ref(declared_type)?; let init = initializer?; - match init { - Expr::Array(values) => { + match &init.kind { + ExprKind::Array(values) => { let mut inferred = element_type.clone(); inferred.array_dims.push(ArrayDim::Fixed(values.len())); if array_literal_matches_type_with_env_ref(values, &inferred, types, constants) { Some(inferred) } else { None } } - Expr::Identifier(name) => { + ExprKind::Identifier(name) => { let other_type = parse_type_ref(types.get(name)?).ok()?; if !is_array_type_ref(&other_type) || array_element_type_ref(&other_type) != Some(element_type.clone()) { return None; @@ -638,15 +626,15 @@ fn infer_fixed_array_type_from_initializer_ref( } } -fn expr_matches_type(expr: &Expr, type_name: &str) -> bool { +fn expr_matches_type<'i>(expr: &Expr<'i>, type_name: &str) -> bool { parse_type_ref(type_name).is_ok_and(|type_ref| expr_matches_type_ref(expr, &type_ref)) } -fn array_literal_matches_type_with_env( - values: &[Expr], +fn array_literal_matches_type_with_env<'i>( + values: &[Expr<'i>], type_name: &str, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { parse_type_ref(type_name).is_ok_and(|type_ref| array_literal_matches_type_with_env_ref(values, &type_ref, types, constants)) } @@ -666,7 +654,7 @@ fn array_size(type_name: &str) -> Option { array_size_ref(&type_ref) } -fn array_size_with_constants(type_name: &str, constants: &HashMap) -> Option { +fn array_size_with_constants<'i>(type_name: &str, constants: &HashMap>) -> Option { let type_ref = parse_type_ref(type_name).ok()?; array_size_with_constants_ref(&type_ref, constants) } @@ -681,7 +669,7 @@ fn array_element_size(type_name: &str) -> Option { array_element_size_ref(&type_ref) } -fn is_type_assignable(actual: &str, expected: &str, constants: &HashMap) -> bool { +fn is_type_assignable<'i>(actual: &str, expected: &str, constants: &HashMap>) -> bool { let Ok(actual_type) = parse_type_ref(actual) else { return false; }; @@ -691,27 +679,27 @@ fn is_type_assignable(actual: &str, expected: &str, constants: &HashMap( + expr: &Expr<'i>, type_name: &str, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { parse_type_ref(type_name).is_ok_and(|type_ref| expr_matches_type_with_env_ref(expr, &type_ref, types, constants)) } -fn infer_fixed_array_type_from_initializer( +fn infer_fixed_array_type_from_initializer<'i>( declared_type: &str, - initializer: Option<&Expr>, + initializer: Option<&Expr<'i>>, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> Option { let declared_type = parse_type_ref(declared_type).ok()?; infer_fixed_array_type_from_initializer_ref(&declared_type, initializer, types, constants).map(|t| type_name_from_ref(&t)) } -impl CompiledContract { - pub fn build_sig_script(&self, function_name: &str, args: Vec) -> Result, CompilerError> { +impl<'i> CompiledContract<'i> { + pub fn build_sig_script(&self, function_name: &str, args: Vec>) -> Result, CompilerError> { let function = self .abi .iter() @@ -735,17 +723,17 @@ impl CompiledContract { let mut builder = ScriptBuilder::new(); for (input, arg) in function.inputs.iter().zip(args) { if is_array_type(&input.type_name) { - match arg { - Expr::Array(ref values) => { - // Check if it's a byte array or other array type + let kind = arg.kind.clone(); + match kind { + ExprKind::Array(values) => { if is_byte_array(&arg) { - // Extract bytes from Expr::Byte array - let bytes: Vec = - values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); + let bytes: Vec = values + .iter() + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) + .collect(); builder.add_data(&bytes)?; } else { - // Regular array - encode it - let bytes = encode_array_literal(values, &input.type_name)?; + let bytes = encode_array_literal(&values, &input.type_name)?; builder.add_data(&bytes)?; } } @@ -768,22 +756,28 @@ impl CompiledContract { } } -fn push_sigscript_arg(builder: &mut ScriptBuilder, arg: Expr) -> Result<(), CompilerError> { - match arg { - Expr::Int(value) => { +fn push_sigscript_arg<'i>(builder: &mut ScriptBuilder, arg: Expr<'i>) -> Result<(), CompilerError> { + match arg.kind { + ExprKind::Int(value) => { builder.add_i64(value)?; } - Expr::Bool(value) => { + ExprKind::Bool(value) => { builder.add_i64(if value { 1 } else { 0 })?; } - Expr::String(value) => { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; } - Expr::Array(values) if is_byte_array(&Expr::Array(values.clone())) => { - // Handle byte arrays - let bytes: Vec = values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); + ExprKind::Byte(value) => { + builder.add_data(&[value])?; + } + ExprKind::Array(values) if values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))) => { + let bytes: Vec = + values.iter().filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }).collect(); builder.add_data(&bytes)?; } + ExprKind::DateLiteral(value) => { + builder.add_i64(value)?; + } _ => { return Err(CompilerError::Unsupported("signature script arguments must be literals".to_string())); } @@ -791,22 +785,23 @@ fn push_sigscript_arg(builder: &mut ScriptBuilder, arg: Expr) -> Result<(), Comp Ok(()) } -fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, CompilerError> { +fn encode_fixed_size_value<'i>(value: &Expr<'i>, type_name: &str) -> Result, CompilerError> { match type_name { "int" => { - let Expr::Int(number) = value else { - return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); + let number = match &value.kind { + ExprKind::Int(number) | ExprKind::DateLiteral(number) => *number, + _ => return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())), }; Ok(number.to_le_bytes().to_vec()) } "bool" => { - let Expr::Bool(flag) = value else { + let ExprKind::Bool(flag) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; Ok(vec![u8::from(*flag)]) } "byte" => { - let Expr::Byte(byte) = value else { + let ExprKind::Byte(byte) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; Ok(vec![*byte]) @@ -818,10 +813,13 @@ fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, Com if len != 32 { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); } - let Expr::Array(bytes_exprs) = value else { + let ExprKind::Array(bytes_exprs) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; - Ok(bytes_exprs.iter().filter_map(|value| if let Expr::Byte(byte) = value { Some(*byte) } else { None }).collect()) + Ok(bytes_exprs + .iter() + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) + .collect()) } _ => { // Handle fixed-size byte arrays like byte[N] @@ -833,18 +831,18 @@ fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, Com if len != size { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); } - let Expr::Array(bytes_exprs) = value else { + let ExprKind::Array(bytes_exprs) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; return Ok(bytes_exprs .iter() - .filter_map(|value| if let Expr::Byte(byte) = value { Some(*byte) } else { None }) + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) .collect()); } } // Handle nested fixed-size arrays with known element sizes. - if let Expr::Array(values) = value { + if let ExprKind::Array(values) = &value.kind { let element_type = array_element_type(type_name) .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; let expected_len = array_size(type_name) @@ -865,7 +863,7 @@ fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, Com } } -fn encode_array_literal(values: &[Expr], type_name: &str) -> Result, CompilerError> { +fn encode_array_literal<'i>(values: &[Expr<'i>], type_name: &str) -> Result, CompilerError> { let element_type = array_element_type(type_name) .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; let mut out = Vec::new(); @@ -878,13 +876,13 @@ fn encode_array_literal(values: &[Expr], type_name: &str) -> Result, Com Ok(out) } -fn infer_fixed_type_from_literal_expr(expr: &Expr) -> Option { - match expr { - Expr::Int(_) => Some("int".to_string()), - Expr::Bool(_) => Some("bool".to_string()), - Expr::Byte(_) => Some("byte".to_string()), - Expr::Array(values) if is_byte_array(expr) => Some(format!("byte[{}]", values.len())), - Expr::Array(values) => { +fn infer_fixed_type_from_literal_expr<'i>(expr: &Expr<'i>) -> Option { + match &expr.kind { + ExprKind::Int(_) | ExprKind::DateLiteral(_) => Some("int".to_string()), + ExprKind::Bool(_) => Some("bool".to_string()), + ExprKind::Byte(_) => Some("byte".to_string()), + ExprKind::Array(values) if is_byte_array(expr) => Some(format!("byte[{}]", values.len())), + ExprKind::Array(values) => { let nested_type = infer_fixed_array_literal_type(values)?; Some(nested_type.trim_end_matches("[]").to_string()) } @@ -892,7 +890,7 @@ fn infer_fixed_type_from_literal_expr(expr: &Expr) -> Option { } } -fn infer_fixed_array_literal_type(values: &[Expr]) -> Option { +fn infer_fixed_array_literal_type<'i>(values: &[Expr<'i>]) -> Option { if values.is_empty() { return None; } @@ -905,7 +903,7 @@ fn infer_fixed_array_literal_type(values: &[Expr]) -> Option { } } -pub fn function_branch_index(contract: &ContractAst, function_name: &str) -> Result { +pub fn function_branch_index<'i>(contract: &ContractAst<'i>, function_name: &str) -> Result { contract .functions .iter() @@ -916,23 +914,23 @@ pub fn function_branch_index(contract: &ContractAst, function_name: &str) -> Res } #[derive(Debug)] -struct CompiledFunction { +struct CompiledFunction<'i> { name: String, script: Vec, - debug: FunctionDebugRecorder, + debug: FunctionDebugRecorder<'i>, } -fn compile_function( - function: &FunctionAst, +fn compile_function<'i>( + function: &FunctionAst<'i>, function_index: usize, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - constants: &HashMap, + constants: &HashMap>, options: CompileOptions, - functions: &HashMap, + functions: &HashMap>, function_order: &HashMap, script_size: Option, -) -> Result { +) -> Result, CompilerError> { let contract_field_count = contract_fields.len(); let param_count = function.params.len(); let mut params = function @@ -964,16 +962,15 @@ fn compile_function( return Err(CompilerError::Unsupported(format!("array element type must have known size: {return_type_name}"))); } } - let mut env: HashMap = constants.clone(); + let mut env: HashMap> = constants.clone(); // `env` is checked before `params` during identifier compilation. - // Remove any constructor-constant names that collide with function params, - // otherwise the compiler would inline the constant and ignore the runtime arg. + // Remove any constructor-constant names that collide with function params. for param in &function.params { env.remove(¶m.name); } let mut builder = ScriptBuilder::new(); let mut recorder = FunctionDebugRecorder::new(options.record_debug_infos, function, contract_fields); - let mut yields: Vec = Vec::new(); + let mut yields: Vec> = Vec::new(); if !options.allow_yield && function.body.iter().any(contains_yield) { return Err(CompilerError::Unsupported("yield requires allow_yield=true".to_string())); @@ -985,7 +982,7 @@ fn compile_function( let has_return = function.body.iter().any(contains_return); if has_return { - if !matches!(function.body.last(), Some(Statement { kind: StatementKind::Return { .. }, .. })) { + if !matches!(function.body.last(), Some(Statement::Return { .. })) { return Err(CompilerError::Unsupported("return statement must be the last statement".to_string())); } if function.body[..function.body.len() - 1].iter().any(contains_return) { @@ -1002,16 +999,14 @@ fn compile_function( let body_len = function.body.len(); for (index, stmt) in function.body.iter().enumerate() { let start = builder.script().len(); - // Snapshot only when debug is enabled; used to derive per-statement var updates. let env_before = recorder.is_enabled().then(|| env.clone()); - if matches!(stmt.kind, StatementKind::Return { .. }) { + if let Statement::Return { exprs, .. } = stmt { if index != body_len - 1 { return Err(CompilerError::Unsupported("return statement must be the last statement".to_string())); } - let StatementKind::Return { exprs } = &stmt.kind else { unreachable!() }; validate_return_types(exprs, &function.return_types, &types, constants)?; for expr in exprs { - let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new())?; + let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new()).map_err(|err| err.with_span(&expr.span))?; yields.push(resolved); } recorder.record_statement_with_env_diff(stmt, start, builder.script().len(), env_before.as_ref(), &env, &types)?; @@ -1033,7 +1028,8 @@ fn compile_function( &mut yields, script_size, &mut recorder, - )?; + ) + .map_err(|err| err.with_span(&stmt.span()))?; let end = builder.script().len(); recorder.record_statement_with_env_diff(stmt, start, end, env_before.as_ref(), &env, &types)?; } @@ -1078,25 +1074,25 @@ fn compile_function( } #[allow(clippy::too_many_arguments)] -fn compile_statement( - stmt: &Statement, - env: &mut HashMap, +fn compile_statement<'i>( + stmt: &Statement<'i>, + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, - debug_recorder: &mut FunctionDebugRecorder, + debug_recorder: &mut FunctionDebugRecorder<'i>, ) -> Result<(), CompilerError> { - match &stmt.kind { - StatementKind::VariableDefinition { type_ref, name, expr, .. } => { + match stmt { + Statement::VariableDefinition { type_ref, name, expr, .. } => { let type_name = type_name_from_ref(type_ref); let effective_type_name = if is_array_type(&type_name) && array_size_with_constants(&type_name, contract_constants).is_none() { @@ -1121,9 +1117,9 @@ fn compile_statement( let is_byte_array_type = effective_type_name.starts_with("byte[") && effective_type_name.ends_with("[]"); let initial = match expr { - Some(Expr::Identifier(other)) => match types.get(other) { + Some(Expr { kind: ExprKind::Identifier(other), .. }) => match types.get(other) { Some(other_type) if is_type_assignable(other_type, &effective_type_name, contract_constants) => { - Expr::Identifier(other.clone()) + Expr::new(ExprKind::Identifier(other.clone()), span::Span::default()) } Some(_) => { return Err(CompilerError::Unsupported("array assignment requires compatible array types".to_string())); @@ -1134,14 +1130,14 @@ fn compile_statement( // byte[] can be initialized from any bytes expression e.clone() } - Some(Expr::Array(values)) => { + Some(e @ Expr { kind: ExprKind::Array(values), .. }) => { if !array_literal_matches_type_with_env(values, &effective_type_name, types, contract_constants) { return Err(CompilerError::Unsupported("array initializer must be another array".to_string())); } - resolve_expr(Expr::Array(values.clone()), env, &mut HashSet::new())? + resolve_expr(Expr::new(ExprKind::Array(values.clone()), e.span), env, &mut HashSet::new())? } Some(_) => return Err(CompilerError::Unsupported("array initializer must be another array".to_string())), - None => Expr::Array(Vec::new()), + None => Expr::new(ExprKind::Array(Vec::new()), span::Span::default()), }; env.insert(name.clone(), initial); types.insert(name.clone(), effective_type_name.clone()); @@ -1152,7 +1148,7 @@ fn compile_statement( expr.clone().ok_or_else(|| CompilerError::Unsupported("variable definition requires initializer".to_string()))?; // For array literals, validate that the size matches the declared type - if let Expr::Array(values) = &expr { + if let ExprKind::Array(values) = &expr.kind { if let Some(expected_size) = array_size_with_constants(&effective_type_name, contract_constants) { if values.len() != expected_size { return Err(CompilerError::Unsupported(format!( @@ -1173,7 +1169,8 @@ fn compile_statement( } } - let stored_expr = if matches!(expr, Expr::Array(_)) { resolve_expr(expr, env, &mut HashSet::new())? } else { expr }; + let stored_expr = + if matches!(&expr.kind, ExprKind::Array(_)) { resolve_expr(expr, env, &mut HashSet::new())? } else { expr }; env.insert(name.clone(), stored_expr); types.insert(name.clone(), effective_type_name.clone()); Ok(()) @@ -1185,7 +1182,7 @@ fn compile_statement( Ok(()) } } - StatementKind::ArrayPush { name, expr } => { + Statement::ArrayPush { name, expr, .. } => { let array_type = types.get(name).ok_or_else(|| CompilerError::UndefinedIdentifier(name.clone()))?; if !is_array_type(array_type) { return Err(CompilerError::Unsupported("push() only supported on arrays".to_string())); @@ -1195,9 +1192,15 @@ fn compile_statement( let _element_size = array_element_size(array_type) .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; let element_expr = if element_type == "int" { - Expr::Call { name: "byte[8]".to_string(), args: vec![expr.clone()] } + Expr::new( + ExprKind::Call { name: "byte[8]".to_string(), args: vec![expr.clone()], name_span: span::Span::default() }, + span::Span::default(), + ) } else if element_type == "byte" { - Expr::Call { name: "byte[1]".to_string(), args: vec![expr.clone()] } + Expr::new( + ExprKind::Call { name: "byte[1]".to_string(), args: vec![expr.clone()], name_span: span::Span::default() }, + span::Span::default(), + ) } else if element_type.contains('[') && element_type.starts_with("byte") { // Handle byte[N] type if expr_is_bytes(expr, env, types) { @@ -1211,7 +1214,14 @@ fn compile_statement( if base_type == "byte" { if let Ok(_size) = size_str.parse::() { // Cast expression to byte[N] - Expr::Call { name: element_type.to_string(), args: vec![expr.clone()] } + Expr::new( + ExprKind::Call { + name: element_type.to_string(), + args: vec![expr.clone()], + name_span: span::Span::default(), + }, + span::Span::default(), + ) } else { return Err(CompilerError::Unsupported("invalid array size".to_string())); } @@ -1229,12 +1239,15 @@ fn compile_statement( return Err(CompilerError::Unsupported("array element type not supported".to_string())); }; - let current = env.get(name).cloned().unwrap_or_else(|| Expr::Array(Vec::new())); - let updated = Expr::Binary { op: BinaryOp::Add, left: Box::new(current), right: Box::new(element_expr) }; + let current = env.get(name).cloned().unwrap_or_else(|| Expr::new(ExprKind::Array(Vec::new()), span::Span::default())); + let updated = Expr::new( + ExprKind::Binary { op: BinaryOp::Add, left: Box::new(current), right: Box::new(element_expr) }, + span::Span::default(), + ); env.insert(name.clone(), updated); Ok(()) } - StatementKind::Require { expr, .. } => { + Statement::Require { expr, .. } => { let mut stack_depth = 0i64; compile_expr( expr, @@ -1251,10 +1264,10 @@ fn compile_statement( builder.add_op(OpVerify)?; Ok(()) } - StatementKind::TimeOp { tx_var, expr, .. } => { + Statement::TimeOp { tx_var, expr, .. } => { compile_time_op_statement(tx_var, expr, env, params, types, builder, options, script_size, contract_constants) } - StatementKind::If { condition, then_branch, else_branch } => compile_if_statement( + Statement::If { condition, then_branch, else_branch, .. } => compile_if_statement( condition, then_branch, else_branch.as_deref(), @@ -1273,7 +1286,7 @@ fn compile_statement( script_size, debug_recorder, ), - StatementKind::For { ident, start, end, body } => compile_for_statement( + Statement::For { ident, start, end, body, .. } => compile_for_statement( ident, start, end, @@ -1293,22 +1306,30 @@ fn compile_statement( script_size, debug_recorder, ), - StatementKind::Yield { expr } => { + Statement::Yield { expr, .. } => { let mut visiting = HashSet::new(); let resolved = resolve_expr(expr.clone(), env, &mut visiting)?; yields.push(resolved); Ok(()) } - StatementKind::Return { .. } => Err(CompilerError::Unsupported("return statement must be the last statement".to_string())), - StatementKind::TupleAssignment { left_name, right_name, expr, .. } => match expr.clone() { - Expr::Split { source, index, .. } => { - env.insert(left_name.clone(), Expr::Split { source: source.clone(), index: index.clone(), part: SplitPart::Left }); - env.insert(right_name.clone(), Expr::Split { source, index, part: SplitPart::Right }); + Statement::Return { .. } => Err(CompilerError::Unsupported("return statement must be the last statement".to_string())), + Statement::TupleAssignment { left_name, right_name, expr, .. } => match &expr.kind { + ExprKind::Split { source, index, span: split_span, .. } => { + let left_expr = Expr::new( + ExprKind::Split { source: source.clone(), index: index.clone(), part: SplitPart::Left, span: *split_span }, + span::Span::default(), + ); + let right_expr = Expr::new( + ExprKind::Split { source: source.clone(), index: index.clone(), part: SplitPart::Right, span: *split_span }, + span::Span::default(), + ); + env.insert(left_name.clone(), left_expr); + env.insert(right_name.clone(), right_expr); Ok(()) } _ => Err(CompilerError::Unsupported("tuple assignment only supports split()".to_string())), }, - StatementKind::FunctionCall { name, args } => { + Statement::FunctionCall { name, args, .. } => { if name == "validateOutputState" { return compile_validate_output_state_statement( args, @@ -1326,7 +1347,7 @@ fn compile_statement( let returns = compile_inline_call( name, args, - stmt.span, + Some(SourceSpan::from(stmt.span())), params, types, env, @@ -1360,7 +1381,7 @@ fn compile_statement( } Ok(()) } - StatementKind::StateFunctionCallAssign { bindings, name, args } => { + Statement::StateFunctionCallAssign { bindings, name, args, .. } => { if name == "readInputState" { return compile_read_input_state_statement( bindings, @@ -1377,7 +1398,7 @@ fn compile_statement( name ))) } - StatementKind::FunctionCallAssign { bindings, name, args } => { + Statement::FunctionCallAssign { bindings, name, args, .. } => { let function = functions.get(name).ok_or_else(|| CompilerError::Unsupported(format!("function '{}' not found", name)))?; if function.return_types.is_empty() { return Err(CompilerError::Unsupported("function has no return types".to_string())); @@ -1395,7 +1416,7 @@ fn compile_statement( let returns = compile_inline_call( name, args, - stmt.span, + Some(SourceSpan::from(stmt.span())), params, types, env, @@ -1417,13 +1438,13 @@ fn compile_statement( } Ok(()) } - StatementKind::Assign { name, expr } => { + Statement::Assign { name, expr, .. } => { if let Some(type_name) = types.get(name) { if is_array_type(type_name) { - match expr { - Expr::Identifier(other) => match types.get(other) { + match &expr.kind { + ExprKind::Identifier(other) => match types.get(other) { Some(other_type) if is_type_assignable(other_type, type_name, contract_constants) => { - env.insert(name.clone(), Expr::Identifier(other.clone())); + env.insert(name.clone(), Expr::new(ExprKind::Identifier(other.clone()), span::Span::default())); return Ok(()); } Some(_) => { @@ -1433,7 +1454,9 @@ fn compile_statement( } None => return Err(CompilerError::UndefinedIdentifier(other.clone())), }, - _ => return Err(CompilerError::Unsupported("array assignment only supports array identifiers".to_string())), + _ => { + return Err(CompilerError::Unsupported("array assignment only supports array identifiers".to_string())); + } } } } @@ -1442,11 +1465,14 @@ fn compile_statement( env.insert(name.clone(), resolved); Ok(()) } - StatementKind::Console { .. } => Ok(()), + Statement::Console { .. } => Ok(()), } } -fn encoded_field_chunk_size(field: &ContractFieldAst, contract_constants: &HashMap) -> Result { +fn encoded_field_chunk_size<'i>( + field: &ContractFieldAst<'i>, + contract_constants: &HashMap>, +) -> Result { if field.type_ref.array_dims.is_empty() && field.type_ref.base == TypeBase::Int { return Ok(10); } @@ -1469,13 +1495,13 @@ fn encoded_field_chunk_size(field: &ContractFieldAst, contract_constants: &HashM Ok(data_prefix(payload_size).len() + payload_size) } -fn read_input_state_binding_expr( - input_idx: &Expr, - field: &ContractFieldAst, +fn read_input_state_binding_expr<'i>( + input_idx: &Expr<'i>, + field: &ContractFieldAst<'i>, field_chunk_offset: usize, script_size_value: i64, - contract_constants: &HashMap, -) -> Result { + contract_constants: &HashMap>, +) -> Result, CompilerError> { let (field_payload_offset, field_payload_len, decode_int) = if field.type_ref.array_dims.is_empty() && field.type_ref.base == TypeBase::Int { (field_chunk_offset + 1, 8usize, true) @@ -1498,26 +1524,35 @@ fn read_input_state_binding_expr( ))); }; - let sig_len = Expr::Call { name: "OpTxInputScriptSigLen".to_string(), args: vec![input_idx.clone()] }; - let start = Expr::Binary { - op: BinaryOp::Add, - left: Box::new(Expr::Binary { op: BinaryOp::Sub, left: Box::new(sig_len), right: Box::new(Expr::Int(script_size_value)) }), - right: Box::new(Expr::Int(field_payload_offset as i64)), - }; - let end = Expr::Binary { op: BinaryOp::Add, left: Box::new(start.clone()), right: Box::new(Expr::Int(field_payload_len as i64)) }; - let substr = Expr::Call { name: "OpTxInputScriptSigSubstr".to_string(), args: vec![input_idx.clone(), start, end] }; + let sig_len = Expr::call("OpTxInputScriptSigLen", vec![input_idx.clone()]); + let start = Expr::new( + ExprKind::Binary { + op: BinaryOp::Add, + left: Box::new(Expr::new( + ExprKind::Binary { op: BinaryOp::Sub, left: Box::new(sig_len), right: Box::new(Expr::int(script_size_value)) }, + span::Span::default(), + )), + right: Box::new(Expr::int(field_payload_offset as i64)), + }, + span::Span::default(), + ); + let end = Expr::new( + ExprKind::Binary { op: BinaryOp::Add, left: Box::new(start.clone()), right: Box::new(Expr::int(field_payload_len as i64)) }, + span::Span::default(), + ); + let substr = Expr::call("OpTxInputScriptSigSubstr", vec![input_idx.clone(), start, end]); - if decode_int { Ok(Expr::Call { name: "OpBin2Num".to_string(), args: vec![substr] }) } else { Ok(substr) } + if decode_int { Ok(Expr::call("OpBin2Num", vec![substr])) } else { Ok(substr) } } -fn compile_read_input_state_statement( - bindings: &[StateBindingAst], - args: &[Expr], - env: &mut HashMap, +fn compile_read_input_state_statement<'i>( + bindings: &[StateBindingAst<'i>], + args: &[Expr<'i>], + env: &mut HashMap>, types: &mut HashMap, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { if args.len() != 1 { return Err(CompilerError::Unsupported("readInputState(input_idx) expects 1 argument".to_string())); @@ -1528,7 +1563,7 @@ fn compile_read_input_state_statement( let script_size_value = script_size.ok_or_else(|| CompilerError::Unsupported("readInputState requires this.scriptSize".to_string()))?; - let mut bindings_by_field: HashMap<&str, &StateBindingAst> = HashMap::new(); + let mut bindings_by_field: HashMap<&str, &StateBindingAst<'i>> = HashMap::new(); for binding in bindings { if bindings_by_field.insert(binding.field_name.as_str(), binding).is_some() { return Err(CompilerError::Unsupported(format!("duplicate state field '{}'", binding.field_name))); @@ -1565,16 +1600,16 @@ fn compile_read_input_state_statement( #[allow(clippy::too_many_arguments)] fn compile_validate_output_state_statement( - args: &[Expr], - env: &HashMap, + args: &[Expr<'_>], + env: &HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'_>], contract_field_prefix_len: usize, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { if args.len() != 2 { return Err(CompilerError::Unsupported("validateOutputState(output_idx, new_state) expects 2 arguments".to_string())); @@ -1584,7 +1619,7 @@ fn compile_validate_output_state_statement( } let output_idx = &args[0]; - let Expr::StateObject(state_entries) = &args[1] else { + let ExprKind::StateObject(state_entries) = &args[1].kind else { return Err(CompilerError::Unsupported("validateOutputState second argument must be an object literal".to_string())); }; @@ -1736,22 +1771,22 @@ fn compile_validate_output_state_statement( } #[allow(clippy::too_many_arguments)] -fn compile_inline_call( +fn compile_inline_call<'i>( name: &str, - args: &[Expr], + args: &[Expr<'i>], call_span: Option, caller_params: &HashMap, caller_types: &mut HashMap, - caller_env: &mut HashMap, + caller_env: &mut HashMap>, builder: &mut ScriptBuilder, options: CompileOptions, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, caller_index: usize, script_size: Option, - debug_recorder: &mut FunctionDebugRecorder, -) -> Result, CompilerError> { + debug_recorder: &mut FunctionDebugRecorder<'i>, +) -> Result>, CompilerError> { let function = functions.get(name).ok_or_else(|| CompilerError::Unsupported(format!("function '{}' not found", name)))?; let callee_index = function_order.get(name).copied().ok_or_else(|| CompilerError::Unsupported(format!("function '{}' not found", name)))?; @@ -1777,8 +1812,8 @@ fn compile_inline_call( return Err(CompilerError::Unsupported(format!("array element type must have known size: {}", param_type_name))); } } - let mut env: HashMap = contract_constants.clone(); + let mut env: HashMap> = contract_constants.clone(); // Preserve caller synthetic inline bindings so nested inline calls can // continue resolving chains like __arg_inner_0 -> __arg_outer_0. for (name, value) in caller_env.iter() { @@ -1794,12 +1829,11 @@ fn compile_inline_call( let resolved = resolve_expr(arg.clone(), caller_env, &mut HashSet::new())?; let temp_name = format!("__arg_{name}_{index}"); let param_type_name = type_name_from_ref(¶m.type_ref); - // Inline calls bind each callee parameter to a synthetic identifier so - // callee expressions keep a stable name while still pointing at the - // caller-provided argument expression. + // Bind each callee parameter to a synthetic identifier so callee + // expressions keep stable names while pointing to caller expressions. env.insert(temp_name.clone(), resolved.clone()); types.insert(temp_name.clone(), param_type_name.clone()); - env.insert(param.name.clone(), Expr::Identifier(temp_name.clone())); + env.insert(param.name.clone(), Expr::new(ExprKind::Identifier(temp_name.clone()), span::Span::default())); caller_env.insert(temp_name.clone(), resolved); caller_types.insert(temp_name, param_type_name); } @@ -1814,7 +1848,7 @@ fn compile_inline_call( let has_return = function.body.iter().any(contains_return); if has_return { - if !matches!(function.body.last(), Some(Statement { kind: StatementKind::Return { .. }, .. })) { + if !matches!(function.body.last(), Some(Statement::Return { .. })) { return Err(CompilerError::Unsupported("return statement must be the last statement".to_string())); } if function.body[..function.body.len() - 1].iter().any(contains_return) { @@ -1826,27 +1860,25 @@ fn compile_inline_call( } let call_start = builder.script().len(); - // Record call boundary on caller frame and collect callee events in a child frame. let mut inline_recorder = debug_recorder.start_inline_call_recording(call_span, call_start, name); inline_recorder.record_inline_param_updates(function, &env, call_span, call_start)?; - let mut yields: Vec = Vec::new(); - // Use caller parameter stack indexes while compiling callee bytecode so - // identifier resolution can still pick values from the caller frame. + let mut yields: Vec> = Vec::new(); + // Use caller parameter indexes while compiling callee bytecode so + // resolution can still pick values from the caller frame. let params = caller_params.clone(); let body_len = function.body.len(); for (index, stmt) in function.body.iter().enumerate() { let start = builder.script().len(); - // Snapshot only when debug is enabled; used to derive per-statement var updates. let env_before = inline_recorder.is_enabled().then(|| env.clone()); - if matches!(stmt.kind, StatementKind::Return { .. }) { + if let Statement::Return { exprs, .. } = stmt { if index != body_len - 1 { return Err(CompilerError::Unsupported("return statement must be the last statement".to_string())); } - let StatementKind::Return { exprs } = &stmt.kind else { unreachable!() }; - validate_return_types(exprs, &function.return_types, &types, contract_constants)?; + validate_return_types(exprs, &function.return_types, &types, contract_constants) + .map_err(|err| err.with_span(&stmt.span()))?; for expr in exprs { - let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new())?; + let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new()).map_err(|err| err.with_span(&expr.span))?; yields.push(resolved); } inline_recorder.record_statement_with_env_diff(stmt, start, builder.script().len(), env_before.as_ref(), &env, &types)?; @@ -1868,7 +1900,8 @@ fn compile_inline_call( &mut yields, script_size, &mut inline_recorder, - )?; + ) + .map_err(|err| err.with_span(&stmt.span()))?; let end = builder.script().len(); inline_recorder.record_statement_with_env_diff(stmt, start, end, env_before.as_ref(), &env, &types)?; } @@ -1888,24 +1921,24 @@ fn compile_inline_call( } #[allow(clippy::too_many_arguments)] -fn compile_if_statement( - condition: &Expr, - then_branch: &[Statement], - else_branch: Option<&[Statement]>, - env: &mut HashMap, +fn compile_if_statement<'i>( + condition: &Expr<'i>, + then_branch: &[Statement<'i>], + else_branch: Option<&[Statement<'i>]>, + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, - debug_recorder: &mut FunctionDebugRecorder, + debug_recorder: &mut FunctionDebugRecorder<'i>, ) -> Result<(), CompilerError> { let mut stack_depth = 0i64; compile_expr( @@ -1973,12 +2006,12 @@ fn compile_if_statement( Ok(()) } -fn merge_env_after_if( - env: &mut HashMap, - original_env: &HashMap, - then_env: &HashMap, - else_env: &HashMap, - condition: &Expr, +fn merge_env_after_if<'i>( + env: &mut HashMap>, + original_env: &HashMap>, + then_env: &HashMap>, + else_env: &HashMap>, + condition: &Expr<'i>, ) { for (name, original_expr) in original_env { let then_expr = then_env.get(name).unwrap_or(original_expr); @@ -1989,26 +2022,29 @@ fn merge_env_after_if( } else { env.insert( name.clone(), - Expr::IfElse { - condition: Box::new(condition.clone()), - then_expr: Box::new(then_expr.clone()), - else_expr: Box::new(else_expr.clone()), - }, + Expr::new( + ExprKind::IfElse { + condition: Box::new(condition.clone()), + then_expr: Box::new(then_expr.clone()), + else_expr: Box::new(else_expr.clone()), + }, + span::Span::default(), + ), ); } } } -fn compile_time_op_statement( +fn compile_time_op_statement<'i>( tx_var: &TimeVar, - expr: &Expr, - env: &mut HashMap, + expr: &Expr<'i>, + env: &mut HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, options: CompileOptions, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { let mut stack_depth = 0i64; compile_expr(expr, env, params, types, builder, options, &mut HashSet::new(), &mut stack_depth, script_size, contract_constants)?; @@ -2026,26 +2062,25 @@ fn compile_time_op_statement( } #[allow(clippy::too_many_arguments)] -fn compile_block( - statements: &[Statement], - env: &mut HashMap, +fn compile_block<'i>( + statements: &[Statement<'i>], + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, - debug_recorder: &mut FunctionDebugRecorder, + debug_recorder: &mut FunctionDebugRecorder<'i>, ) -> Result<(), CompilerError> { for stmt in statements { let start = builder.script().len(); - // Snapshot only when debug is enabled; used to derive per-statement var updates. let env_before = debug_recorder.is_enabled().then(|| env.clone()); compile_statement( stmt, @@ -2063,7 +2098,8 @@ fn compile_block( yields, script_size, debug_recorder, - )?; + ) + .map_err(|err| err.with_span(&stmt.span()))?; let end = builder.script().len(); debug_recorder.record_statement_with_env_diff(stmt, start, end, env_before.as_ref(), env, types)?; } @@ -2071,25 +2107,25 @@ fn compile_block( } #[allow(clippy::too_many_arguments)] -fn compile_for_statement( +fn compile_for_statement<'i>( ident: &str, - start_expr: &Expr, - end_expr: &Expr, - body: &[Statement], - env: &mut HashMap, + start_expr: &Expr<'i>, + end_expr: &Expr<'i>, + body: &[Statement<'i>], + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, - debug_recorder: &mut FunctionDebugRecorder, + debug_recorder: &mut FunctionDebugRecorder<'i>, ) -> Result<(), CompilerError> { let start = eval_const_int(start_expr, contract_constants)?; let end = eval_const_int(end_expr, contract_constants)?; @@ -2100,7 +2136,7 @@ fn compile_for_statement( let name = ident.to_string(); let previous = env.get(&name).cloned(); for value in start..end { - env.insert(name.clone(), Expr::Int(value)); + env.insert(name.clone(), Expr::int(value)); compile_block( body, env, @@ -2132,16 +2168,17 @@ fn compile_for_statement( Ok(()) } -fn eval_const_int(expr: &Expr, constants: &HashMap) -> Result { - match expr { - Expr::Int(value) => Ok(*value), - Expr::Identifier(name) => match constants.get(name) { +fn eval_const_int<'i>(expr: &Expr<'i>, constants: &HashMap>) -> Result { + match &expr.kind { + ExprKind::Int(value) => Ok(*value), + ExprKind::DateLiteral(value) => Ok(*value), + ExprKind::Identifier(name) => match constants.get(name) { Some(value) => eval_const_int(value, constants), None => Err(CompilerError::Unsupported("for loop bounds must be constant integers".to_string())), }, - Expr::Unary { op: UnaryOp::Neg, expr } => Ok(-eval_const_int(expr, constants)?), - Expr::Unary { .. } => Err(CompilerError::Unsupported("for loop bounds must be constant integers".to_string())), - Expr::Binary { op, left, right } => { + ExprKind::Unary { op: UnaryOp::Neg, expr } => Ok(-eval_const_int(expr, constants)?), + ExprKind::Unary { .. } => Err(CompilerError::Unsupported("for loop bounds must be constant integers".to_string())), + ExprKind::Binary { op, left, right } => { let lhs = eval_const_int(left, constants)?; let rhs = eval_const_int(right, constants)?; match op { @@ -2167,66 +2204,16 @@ fn eval_const_int(expr: &Expr, constants: &HashMap) -> Result Result) -> Result { - match expr { - Expr::Unary { op, expr } => Ok(Expr::Unary { op, expr: Box::new(recurse(*expr)?) }), - Expr::Binary { op, left, right } => { - Ok(Expr::Binary { op, left: Box::new(recurse(*left)?), right: Box::new(recurse(*right)?) }) - } - Expr::IfElse { condition, then_expr, else_expr } => Ok(Expr::IfElse { - condition: Box::new(recurse(*condition)?), - then_expr: Box::new(recurse(*then_expr)?), - else_expr: Box::new(recurse(*else_expr)?), - }), - Expr::Array(values) => { - let mut rewritten = Vec::with_capacity(values.len()); - for value in values { - rewritten.push(recurse(value)?); - } - Ok(Expr::Array(rewritten)) - } - Expr::StateObject(fields) => { - let mut rewritten_fields = Vec::with_capacity(fields.len()); - for field in fields { - rewritten_fields.push(crate::ast::StateFieldExpr { name: field.name, expr: recurse(field.expr)? }); - } - Ok(Expr::StateObject(rewritten_fields)) - } - Expr::Call { name, args } => { - let mut rewritten = Vec::with_capacity(args.len()); - for arg in args { - rewritten.push(recurse(arg)?); - } - Ok(Expr::Call { name, args: rewritten }) - } - Expr::New { name, args } => { - let mut rewritten = Vec::with_capacity(args.len()); - for arg in args { - rewritten.push(recurse(arg)?); - } - Ok(Expr::New { name, args: rewritten }) - } - Expr::Split { source, index, part } => { - Ok(Expr::Split { source: Box::new(recurse(*source)?), index: Box::new(recurse(*index)?), part }) - } - Expr::Slice { source, start, end } => { - Ok(Expr::Slice { source: Box::new(recurse(*source)?), start: Box::new(recurse(*start)?), end: Box::new(recurse(*end)?) }) - } - Expr::ArrayIndex { source, index } => { - Ok(Expr::ArrayIndex { source: Box::new(recurse(*source)?), index: Box::new(recurse(*index)?) }) - } - Expr::Introspection { kind, index } => Ok(Expr::Introspection { kind, index: Box::new(recurse(*index)?) }), - other => Ok(other), - } -} - -fn resolve_expr(expr: Expr, env: &HashMap, visiting: &mut HashSet) -> Result { - match expr { - Expr::Identifier(name) => { - // Keep synthetic inline args unresolved in compile mode so generated - // bytecode still reads them from caller stack bindings. +fn resolve_expr<'i>( + expr: Expr<'i>, + env: &HashMap>, + visiting: &mut HashSet, +) -> Result, CompilerError> { + let Expr { kind, span } = expr; + match kind { + ExprKind::Identifier(name) => { if name.starts_with("__arg_") { - return Ok(Expr::Identifier(name)); + return Ok(Expr::new(ExprKind::Identifier(name), span)); } if let Some(value) = env.get(&name) { if !visiting.insert(name.clone()) { @@ -2236,16 +2223,100 @@ fn resolve_expr(expr: Expr, env: &HashMap, visiting: &mut HashSet< visiting.remove(&name); Ok(resolved) } else { - Ok(Expr::Identifier(name)) + Ok(Expr::new(ExprKind::Identifier(name), span)) + } + } + ExprKind::Unary { op, expr } => { + Ok(Expr::new(ExprKind::Unary { op, expr: Box::new(resolve_expr(*expr, env, visiting)?) }, span)) + } + ExprKind::Binary { op, left, right } => Ok(Expr::new( + ExprKind::Binary { + op, + left: Box::new(resolve_expr(*left, env, visiting)?), + right: Box::new(resolve_expr(*right, env, visiting)?), + }, + span, + )), + ExprKind::IfElse { condition, then_expr, else_expr } => Ok(Expr::new( + ExprKind::IfElse { + condition: Box::new(resolve_expr(*condition, env, visiting)?), + then_expr: Box::new(resolve_expr(*then_expr, env, visiting)?), + else_expr: Box::new(resolve_expr(*else_expr, env, visiting)?), + }, + span, + )), + ExprKind::Array(values) => { + let mut resolved = Vec::with_capacity(values.len()); + for value in values { + resolved.push(resolve_expr(value, env, visiting)?); } + Ok(Expr::new(ExprKind::Array(resolved), span)) } - other => rewrite_expr_children(other, |child| resolve_expr(child, env, visiting)), + ExprKind::StateObject(fields) => { + let mut resolved_fields = Vec::with_capacity(fields.len()); + for field in fields { + resolved_fields.push(StateFieldExpr { + name: field.name, + expr: resolve_expr(field.expr, env, visiting)?, + span: field.span, + name_span: field.name_span, + }); + } + Ok(Expr::new(ExprKind::StateObject(resolved_fields), span)) + } + ExprKind::Call { name, args, name_span } => { + let mut resolved = Vec::with_capacity(args.len()); + for arg in args { + resolved.push(resolve_expr(arg, env, visiting)?); + } + Ok(Expr::new(ExprKind::Call { name, args: resolved, name_span }, span)) + } + ExprKind::New { name, args, name_span } => { + let mut resolved = Vec::with_capacity(args.len()); + for arg in args { + resolved.push(resolve_expr(arg, env, visiting)?); + } + Ok(Expr::new(ExprKind::New { name, args: resolved, name_span }, span)) + } + ExprKind::Split { source, index, part, span: split_span } => Ok(Expr::new( + ExprKind::Split { + source: Box::new(resolve_expr(*source, env, visiting)?), + index: Box::new(resolve_expr(*index, env, visiting)?), + part, + span: split_span, + }, + span, + )), + ExprKind::ArrayIndex { source, index } => Ok(Expr::new( + ExprKind::ArrayIndex { + source: Box::new(resolve_expr(*source, env, visiting)?), + index: Box::new(resolve_expr(*index, env, visiting)?), + }, + span, + )), + ExprKind::Introspection { kind, index, field_span } => { + Ok(Expr::new(ExprKind::Introspection { kind, index: Box::new(resolve_expr(*index, env, visiting)?), field_span }, span)) + } + ExprKind::UnarySuffix { source, kind, span: suffix_span } => Ok(Expr::new( + ExprKind::UnarySuffix { source: Box::new(resolve_expr(*source, env, visiting)?), kind, span: suffix_span }, + span, + )), + ExprKind::Slice { source, start, end, span: slice_span } => Ok(Expr::new( + ExprKind::Slice { + source: Box::new(resolve_expr(*source, env, visiting)?), + start: Box::new(resolve_expr(*start, env, visiting)?), + end: Box::new(resolve_expr(*end, env, visiting)?), + span: slice_span, + }, + span, + )), + other => Ok(Expr::new(other, span)), } } /// Compiles a pre-resolved expression for debugger shadow evaluation. -pub fn compile_debug_expr( - expr: &Expr, +pub fn compile_debug_expr<'i>( + expr: &Expr<'i>, params: &HashMap, types: &HashMap, ) -> Result, CompilerError> { @@ -2268,27 +2339,28 @@ pub fn compile_debug_expr( Ok(builder.drain()) } -pub(super) fn resolve_expr_for_debug( - expr: Expr, - env: &HashMap, +pub(super) fn resolve_expr_for_debug<'i>( + expr: Expr<'i>, + env: &HashMap>, visiting: &mut HashSet, -) -> Result { +) -> Result, CompilerError> { let resolved = resolve_expr(expr, env, visiting)?; expand_inline_arg_placeholders(resolved, env, &mut HashSet::new()) } -fn expand_inline_arg_placeholders( - expr: Expr, - env: &HashMap, +fn expand_inline_arg_placeholders<'i>( + expr: Expr<'i>, + env: &HashMap>, visiting: &mut HashSet, -) -> Result { - match expr { - Expr::Identifier(name) => { +) -> Result, CompilerError> { + let Expr { kind, span } = expr; + match kind { + ExprKind::Identifier(name) => { if !name.starts_with("__arg_") { - return Ok(Expr::Identifier(name)); + return Ok(Expr::new(ExprKind::Identifier(name), span)); } let Some(value) = env.get(&name).cloned() else { - return Ok(Expr::Identifier(name)); + return Ok(Expr::new(ExprKind::Identifier(name), span)); }; if !visiting.insert(name.clone()) { return Err(CompilerError::CyclicIdentifier(name)); @@ -2297,71 +2369,225 @@ fn expand_inline_arg_placeholders( visiting.remove(&name); Ok(expanded) } - other => rewrite_expr_children(other, |child| expand_inline_arg_placeholders(child, env, visiting)), - } -} - -fn replace_identifier(expr: &Expr, target: &str, replacement: &Expr) -> Expr { - match expr { - Expr::Identifier(name) if name == target => replacement.clone(), - Expr::Identifier(_) => expr.clone(), - Expr::Unary { op, expr: inner } => Expr::Unary { op: *op, expr: Box::new(replace_identifier(inner, target, replacement)) }, - Expr::Binary { op, left, right } => Expr::Binary { - op: *op, - left: Box::new(replace_identifier(left, target, replacement)), - right: Box::new(replace_identifier(right, target, replacement)), - }, - Expr::Array(values) => Expr::Array(values.iter().map(|value| replace_identifier(value, target, replacement)).collect()), - Expr::StateObject(fields) => Expr::StateObject( - fields - .iter() - .map(|field| crate::ast::StateFieldExpr { - name: field.name.clone(), - expr: replace_identifier(&field.expr, target, replacement), - }) - .collect(), - ), - Expr::Call { name, args } => { - Expr::Call { name: name.clone(), args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect() } + ExprKind::Unary { op, expr } => Ok(Expr::new( + ExprKind::Unary { op, expr: Box::new(expand_inline_arg_placeholders(*expr, env, visiting)?) }, + span, + )), + ExprKind::Binary { op, left, right } => Ok(Expr::new( + ExprKind::Binary { + op, + left: Box::new(expand_inline_arg_placeholders(*left, env, visiting)?), + right: Box::new(expand_inline_arg_placeholders(*right, env, visiting)?), + }, + span, + )), + ExprKind::IfElse { condition, then_expr, else_expr } => Ok(Expr::new( + ExprKind::IfElse { + condition: Box::new(expand_inline_arg_placeholders(*condition, env, visiting)?), + then_expr: Box::new(expand_inline_arg_placeholders(*then_expr, env, visiting)?), + else_expr: Box::new(expand_inline_arg_placeholders(*else_expr, env, visiting)?), + }, + span, + )), + ExprKind::Array(values) => { + let mut rewritten = Vec::with_capacity(values.len()); + for value in values { + rewritten.push(expand_inline_arg_placeholders(value, env, visiting)?); + } + Ok(Expr::new(ExprKind::Array(rewritten), span)) } - Expr::New { name, args } => { - Expr::New { name: name.clone(), args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect() } + ExprKind::StateObject(fields) => { + let mut rewritten = Vec::with_capacity(fields.len()); + for field in fields { + rewritten.push(StateFieldExpr { + name: field.name, + expr: expand_inline_arg_placeholders(field.expr, env, visiting)?, + span: field.span, + name_span: field.name_span, + }); + } + Ok(Expr::new(ExprKind::StateObject(rewritten), span)) } - Expr::Split { source, index, part } => Expr::Split { - source: Box::new(replace_identifier(source, target, replacement)), - index: Box::new(replace_identifier(index, target, replacement)), - part: *part, - }, - Expr::Slice { source, start, end } => Expr::Slice { - source: Box::new(replace_identifier(source, target, replacement)), - start: Box::new(replace_identifier(start, target, replacement)), - end: Box::new(replace_identifier(end, target, replacement)), - }, - Expr::ArrayIndex { source, index } => Expr::ArrayIndex { - source: Box::new(replace_identifier(source, target, replacement)), - index: Box::new(replace_identifier(index, target, replacement)), - }, - Expr::IfElse { condition, then_expr, else_expr } => Expr::IfElse { - condition: Box::new(replace_identifier(condition, target, replacement)), - then_expr: Box::new(replace_identifier(then_expr, target, replacement)), - else_expr: Box::new(replace_identifier(else_expr, target, replacement)), - }, - Expr::Introspection { kind, index } => { - Expr::Introspection { kind: *kind, index: Box::new(replace_identifier(index, target, replacement)) } + ExprKind::Call { name, args, name_span } => { + let mut rewritten = Vec::with_capacity(args.len()); + for arg in args { + rewritten.push(expand_inline_arg_placeholders(arg, env, visiting)?); + } + Ok(Expr::new(ExprKind::Call { name, args: rewritten, name_span }, span)) } - Expr::Int(_) | Expr::Bool(_) | Expr::Byte(_) | Expr::String(_) | Expr::Nullary(_) => expr.clone(), + ExprKind::New { name, args, name_span } => { + let mut rewritten = Vec::with_capacity(args.len()); + for arg in args { + rewritten.push(expand_inline_arg_placeholders(arg, env, visiting)?); + } + Ok(Expr::new(ExprKind::New { name, args: rewritten, name_span }, span)) + } + ExprKind::Split { source, index, part, span: split_span } => Ok(Expr::new( + ExprKind::Split { + source: Box::new(expand_inline_arg_placeholders(*source, env, visiting)?), + index: Box::new(expand_inline_arg_placeholders(*index, env, visiting)?), + part, + span: split_span, + }, + span, + )), + ExprKind::ArrayIndex { source, index } => Ok(Expr::new( + ExprKind::ArrayIndex { + source: Box::new(expand_inline_arg_placeholders(*source, env, visiting)?), + index: Box::new(expand_inline_arg_placeholders(*index, env, visiting)?), + }, + span, + )), + ExprKind::Introspection { kind, index, field_span } => Ok(Expr::new( + ExprKind::Introspection { + kind, + index: Box::new(expand_inline_arg_placeholders(*index, env, visiting)?), + field_span, + }, + span, + )), + ExprKind::UnarySuffix { source, kind, span: suffix_span } => Ok(Expr::new( + ExprKind::UnarySuffix { + source: Box::new(expand_inline_arg_placeholders(*source, env, visiting)?), + kind, + span: suffix_span, + }, + span, + )), + ExprKind::Slice { source, start, end, span: slice_span } => Ok(Expr::new( + ExprKind::Slice { + source: Box::new(expand_inline_arg_placeholders(*source, env, visiting)?), + start: Box::new(expand_inline_arg_placeholders(*start, env, visiting)?), + end: Box::new(expand_inline_arg_placeholders(*end, env, visiting)?), + span: slice_span, + }, + span, + )), + other => Ok(Expr::new(other, span)), + } +} + +/// Replace `target` identifiers in `expr` with `replacement`. +/// +/// Example: for `x = x + 1`, this rewrites the right side to +/// ` + 1` before `resolve_expr` runs. +fn replace_identifier<'i>(expr: &Expr<'i>, target: &str, replacement: &Expr<'i>) -> Expr<'i> { + let span = expr.span; + match &expr.kind { + ExprKind::Identifier(name) if name == target => replacement.clone(), + ExprKind::Identifier(_) => expr.clone(), + ExprKind::Unary { op, expr: inner } => { + Expr::new(ExprKind::Unary { op: *op, expr: Box::new(replace_identifier(inner, target, replacement)) }, span) + } + ExprKind::Binary { op, left, right } => Expr::new( + ExprKind::Binary { + op: *op, + left: Box::new(replace_identifier(left, target, replacement)), + right: Box::new(replace_identifier(right, target, replacement)), + }, + span, + ), + ExprKind::Array(values) => { + Expr::new(ExprKind::Array(values.iter().map(|value| replace_identifier(value, target, replacement)).collect()), span) + } + ExprKind::StateObject(fields) => Expr::new( + ExprKind::StateObject( + fields + .iter() + .map(|field| StateFieldExpr { + name: field.name.clone(), + expr: replace_identifier(&field.expr, target, replacement), + span: field.span, + name_span: field.name_span, + }) + .collect(), + ), + span, + ), + ExprKind::Call { name, args, name_span } => Expr::new( + ExprKind::Call { + name: name.clone(), + args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect(), + name_span: *name_span, + }, + span, + ), + ExprKind::New { name, args, name_span } => Expr::new( + ExprKind::New { + name: name.clone(), + args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect(), + name_span: *name_span, + }, + span, + ), + ExprKind::Split { source, index, part, span: split_span } => Expr::new( + ExprKind::Split { + source: Box::new(replace_identifier(source, target, replacement)), + index: Box::new(replace_identifier(index, target, replacement)), + part: *part, + span: *split_span, + }, + span, + ), + ExprKind::Slice { source, start, end, span: slice_span } => Expr::new( + ExprKind::Slice { + source: Box::new(replace_identifier(source, target, replacement)), + start: Box::new(replace_identifier(start, target, replacement)), + end: Box::new(replace_identifier(end, target, replacement)), + span: *slice_span, + }, + span, + ), + ExprKind::ArrayIndex { source, index } => Expr::new( + ExprKind::ArrayIndex { + source: Box::new(replace_identifier(source, target, replacement)), + index: Box::new(replace_identifier(index, target, replacement)), + }, + span, + ), + ExprKind::IfElse { condition, then_expr, else_expr } => Expr::new( + ExprKind::IfElse { + condition: Box::new(replace_identifier(condition, target, replacement)), + then_expr: Box::new(replace_identifier(then_expr, target, replacement)), + else_expr: Box::new(replace_identifier(else_expr, target, replacement)), + }, + span, + ), + ExprKind::Introspection { kind, index, field_span } => Expr::new( + ExprKind::Introspection { + kind: *kind, + index: Box::new(replace_identifier(index, target, replacement)), + field_span: *field_span, + }, + span, + ), + ExprKind::UnarySuffix { source, kind, span: suffix_span } => Expr::new( + ExprKind::UnarySuffix { + source: Box::new(replace_identifier(source, target, replacement)), + kind: *kind, + span: *suffix_span, + }, + span, + ), + ExprKind::Int(_) + | ExprKind::Bool(_) + | ExprKind::Byte(_) + | ExprKind::String(_) + | ExprKind::DateLiteral(_) + | ExprKind::NumberWithUnit { .. } + | ExprKind::Nullary(_) => expr.clone(), } } -struct CompilationScope<'a> { - env: &'a HashMap, +struct CompilationScope<'a, 'i> { + env: &'a HashMap>, params: &'a HashMap, types: &'a HashMap, } -fn compile_expr( - expr: &Expr, - env: &HashMap, +fn compile_expr<'i>( + expr: &Expr<'i>, + env: &HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, @@ -2369,63 +2595,60 @@ fn compile_expr( visiting: &mut HashSet, stack_depth: &mut i64, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { let scope = CompilationScope { env, params, types }; - match expr { - Expr::Int(value) => { + match &expr.kind { + ExprKind::Int(value) => { builder.add_i64(*value)?; *stack_depth += 1; Ok(()) } - Expr::Bool(value) => { + ExprKind::Bool(value) => { builder.add_op(if *value { OpTrue } else { OpFalse })?; *stack_depth += 1; Ok(()) } - Expr::Byte(b) => { - builder.add_data(&[*b])?; - *stack_depth += 1; - Ok(()) - } - Expr::Array(values) if is_byte_array(&Expr::Array(values.clone())) => { - // Handle byte arrays - let bytes: Vec = values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); - builder.add_data(&bytes)?; + ExprKind::Byte(byte) => { + builder.add_data(&[*byte])?; *stack_depth += 1; Ok(()) } - Expr::Array(values) => { - if let Some(array_type) = infer_fixed_array_literal_type(values) { - let encoded = encode_array_literal(values, &array_type)?; - builder.add_data(&encoded)?; + ExprKind::Array(values) => { + if values.is_empty() { + builder.add_data(&[])?; *stack_depth += 1; return Ok(()); } - Err(CompilerError::Unsupported( - "array literals are only supported for fixed-size element arrays and in LockingBytecodeNullData".to_string(), - )) + let inferred_type = infer_fixed_array_literal_type(values) + .ok_or_else(|| CompilerError::Unsupported("array literal type cannot be inferred".to_string()))?; + let encoded = encode_array_literal(values, &inferred_type)?; + builder.add_data(&encoded)?; + *stack_depth += 1; + Ok(()) } - Expr::StateObject(_) => { - Err(CompilerError::Unsupported("state object literals are only supported in validateOutputState()".to_string())) + ExprKind::StateObject(_) => { + Err(CompilerError::Unsupported("state object literals are only supported in validateOutputState".to_string())) } - Expr::String(value) => { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; *stack_depth += 1; Ok(()) } - Expr::Identifier(name) => { + ExprKind::Identifier(name) => { if !visiting.insert(name.clone()) { return Err(CompilerError::CyclicIdentifier(name.clone())); } if let Some(expr) = env.get(name) { - if let (Some(type_name), Expr::Array(values)) = (types.get(name), expr) { - if is_array_type(type_name) { - let encoded = encode_array_literal(values, type_name)?; - builder.add_data(&encoded)?; - *stack_depth += 1; - visiting.remove(name); - return Ok(()); + if let Some(type_name) = types.get(name) { + if let ExprKind::Array(values) = &expr.kind { + if is_array_type(type_name) { + let encoded = encode_array_literal(values, type_name)?; + builder.add_data(&encoded)?; + *stack_depth += 1; + visiting.remove(name); + return Ok(()); + } } } compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; @@ -2442,7 +2665,7 @@ fn compile_expr( visiting.remove(name); Err(CompilerError::UndefinedIdentifier(name.clone())) } - Expr::IfElse { condition, then_expr, else_expr } => { + ExprKind::IfElse { condition, then_expr, else_expr } => { compile_expr(condition, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; builder.add_op(OpIf)?; *stack_depth -= 1; @@ -2455,557 +2678,942 @@ fn compile_expr( *stack_depth = depth_before + 1; Ok(()) } - Expr::Call { name, args } => match name.as_str() { - "OpSha256" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpSHA256, - script_size, - contract_constants, - ), - "sha256" => { + ExprKind::Call { name, args, .. } => { + compile_call_expr(name.as_str(), args, &scope, builder, options, visiting, stack_depth, script_size, contract_constants) + } + ExprKind::New { name, args, .. } => match name.as_str() { + "LockingBytecodeNullData" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("LockingBytecodeNullData expects a single array argument".to_string())); + } + let script = build_null_data_script(&args[0])?; + builder.add_data(&script)?; + *stack_depth += 1; + Ok(()) + } + "ScriptPubKeyP2PK" => { if args.len() != 1 { - return Err(CompilerError::Unsupported("sha256() expects a single argument".to_string())); + return Err(CompilerError::Unsupported("ScriptPubKeyP2PK expects a single pubkey argument".to_string())); } compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpSHA256)?; + builder.add_data(&[0x00, 0x00, OpData32])?; + *stack_depth += 1; + builder.add_op(OpSwap)?; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[OpCheckSig])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; Ok(()) } - "date" => { + "ScriptPubKeyP2SH" => { if args.len() != 1 { - return Err(CompilerError::Unsupported("date() expects a single argument".to_string())); + return Err(CompilerError::Unsupported("ScriptPubKeyP2SH expects a single bytes32 argument".to_string())); } - let value = match &args[0] { - Expr::String(value) => value.as_str(), - Expr::Identifier(name) => { - if let Some(Expr::String(value)) = env.get(name) { - value.as_str() - } else { - return Err(CompilerError::Unsupported("date() expects a string literal".to_string())); - } - } - _ => return Err(CompilerError::Unsupported("date() expects a string literal".to_string())), - }; - let timestamp = parse_date_value(value)?; - builder.add_i64(timestamp)?; + compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_data(&[0x00, 0x00])?; + *stack_depth += 1; + builder.add_data(&[OpBlake2b])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[0x20])?; *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_op(OpSwap)?; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[OpEqual])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; Ok(()) } - "OpTxSubnetId" => compile_opcode_call( - name, - args, - 0, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxSubnetId, - script_size, - contract_constants, - ), - "OpTxGas" => compile_opcode_call( - name, - args, - 0, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxGas, - script_size, - contract_constants, - ), - "OpTxPayloadLen" => compile_opcode_call( - name, - args, - 0, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxPayloadLen, - script_size, - contract_constants, - ), - "OpTxPayloadSubstr" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxPayloadSubstr, - script_size, - contract_constants, - ), - "OpOutpointTxId" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpOutpointTxId, - script_size, - contract_constants, - ), - "OpOutpointIndex" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpOutpointIndex, - script_size, - contract_constants, - ), - "OpTxInputScriptSigLen" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputScriptSigLen, - script_size, - contract_constants, - ), - "OpTxInputScriptSigSubstr" => compile_opcode_call( - name, - args, - 3, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputScriptSigSubstr, - script_size, - contract_constants, - ), - "OpTxInputSeq" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputSeq, - script_size, - contract_constants, - ), - "OpTxInputIsCoinbase" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputIsCoinbase, - script_size, - contract_constants, - ), - "OpTxInputSpkLen" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputSpkLen, - script_size, - contract_constants, - ), - "OpTxInputSpkSubstr" => compile_opcode_call( - name, - args, - 3, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputSpkSubstr, - script_size, - contract_constants, - ), - "OpTxOutputSpkLen" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxOutputSpkLen, - script_size, - contract_constants, - ), - "OpTxOutputSpkSubstr" => compile_opcode_call( - name, - args, - 3, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxOutputSpkSubstr, - script_size, - contract_constants, - ), - "OpAuthOutputCount" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpAuthOutputCount, - script_size, - contract_constants, - ), - "OpAuthOutputIdx" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpAuthOutputIdx, - script_size, - contract_constants, - ), - "OpInputCovenantId" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpInputCovenantId, - script_size, - contract_constants, - ), - "OpCovInputCount" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovInputCount, - script_size, - contract_constants, - ), - "OpCovInputIdx" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovInputIdx, - script_size, - contract_constants, - ), - "OpCovOutCount" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovOutCount, - script_size, - contract_constants, - ), - "OpCovOutputIdx" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovOutputIdx, - script_size, - contract_constants, - ), - "OpNum2Bin" => compile_opcode_call( - name, - args, - 2, - &scope, + "ScriptPubKeyP2SHFromRedeemScript" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported( + "ScriptPubKeyP2SHFromRedeemScript expects a single redeem_script argument".to_string(), + )); + } + compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_op(OpBlake2b)?; + builder.add_data(&[0x00, 0x00])?; + *stack_depth += 1; + builder.add_data(&[OpBlake2b])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[0x20])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_op(OpSwap)?; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[OpEqual])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + Ok(()) + } + name => Err(CompilerError::Unsupported(format!("unknown constructor: {name}"))), + }, + ExprKind::Unary { op, expr } => { + compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + match op { + UnaryOp::Not => builder.add_op(OpNot)?, + UnaryOp::Neg => builder.add_op(OpNegate)?, + }; + Ok(()) + } + ExprKind::Binary { op, left, right } => { + let bytes_eq = + matches!(op, BinaryOp::Eq | BinaryOp::Ne) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); + let bytes_add = matches!(op, BinaryOp::Add) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); + if bytes_add { + compile_concat_operand( + left, + env, + params, + types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + compile_concat_operand( + right, + env, + params, + types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + } else { + compile_expr(left, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + compile_expr(right, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + } + match op { + BinaryOp::Or => { + builder.add_op(OpBoolOr)?; + } + BinaryOp::And => { + builder.add_op(OpBoolAnd)?; + } + BinaryOp::BitOr => { + builder.add_op(OpOr)?; + } + BinaryOp::BitXor => { + builder.add_op(OpXor)?; + } + BinaryOp::BitAnd => { + builder.add_op(OpAnd)?; + } + BinaryOp::Eq => { + builder.add_op(if bytes_eq { OpEqual } else { OpNumEqual })?; + } + BinaryOp::Ne => { + if bytes_eq { + builder.add_op(OpEqual)?; + builder.add_op(OpNot)?; + } else { + builder.add_op(OpNumNotEqual)?; + } + } + BinaryOp::Lt => { + builder.add_op(OpLessThan)?; + } + BinaryOp::Le => { + builder.add_op(OpLessThanOrEqual)?; + } + BinaryOp::Gt => { + builder.add_op(OpGreaterThan)?; + } + BinaryOp::Ge => { + builder.add_op(OpGreaterThanOrEqual)?; + } + BinaryOp::Add => { + if bytes_add { + builder.add_op(OpCat)?; + } else { + builder.add_op(OpAdd)?; + } + } + BinaryOp::Sub => { + builder.add_op(OpSub)?; + } + BinaryOp::Mul => { + builder.add_op(OpMul)?; + } + BinaryOp::Div => { + builder.add_op(OpDiv)?; + } + BinaryOp::Mod => { + builder.add_op(OpMod)?; + } + } + *stack_depth -= 1; + Ok(()) + } + ExprKind::Split { source, index, part, .. } => compile_split_part( + source, + index, + *part, + env, + params, + types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + ), + ExprKind::UnarySuffix { source, kind, .. } => match kind { + UnarySuffixKind::Length => compile_length_expr( + source, + env, + params, + types, builder, options, visiting, stack_depth, - OpNum2Bin, script_size, contract_constants, ), - "OpBin2Num" => compile_opcode_call( - name, - args, - 1, - &scope, + UnarySuffixKind::Reverse => Err(CompilerError::Unsupported("reverse() is not supported".to_string())), + }, + ExprKind::ArrayIndex { source, index } => { + let resolved_source = match source.as_ref() { + Expr { kind: ExprKind::Identifier(_), .. } => source.as_ref().clone(), + _ => resolve_expr(*source.clone(), env, visiting)?, + }; + let element_type = match &resolved_source.kind { + ExprKind::Identifier(name) => { + let type_name = types.get(name).or_else(|| { + env.get(name).and_then(|value| match &value.kind { + ExprKind::Identifier(inner) => types.get(inner), + _ => None, + }) + }); + type_name + .and_then(|t| array_element_type(t)) + .ok_or_else(|| CompilerError::Unsupported(format!("array index requires array identifier: {name}")))? + } + _ => return Err(CompilerError::Unsupported("array index requires array identifier".to_string())), + }; + let element_size = fixed_type_size(&element_type) + .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; + compile_expr( + &resolved_source, + env, + params, + types, builder, options, visiting, stack_depth, - OpBin2Num, script_size, contract_constants, - ), - "OpChainblockSeqCommit" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpChainblockSeqCommit, - script_size, - contract_constants, - ), - "bytes" => { - if args.is_empty() || args.len() > 2 { - return Err(CompilerError::Unsupported("bytes() expects one or two arguments".to_string())); + )?; + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_i64(element_size)?; + *stack_depth += 1; + builder.add_op(OpMul)?; + *stack_depth -= 1; + builder.add_op(OpDup)?; + *stack_depth += 1; + builder.add_i64(element_size)?; + *stack_depth += 1; + builder.add_op(OpAdd)?; + *stack_depth -= 1; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + if element_type == "int" { + builder.add_op(OpBin2Num)?; + } + Ok(()) + } + ExprKind::Slice { source, start, end, .. } => { + compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + compile_expr(start, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + compile_expr(end, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + + builder.add_op(Op2Dup)?; + *stack_depth += 2; + builder.add_op(OpSwap)?; + builder.add_op(OpSub)?; + *stack_depth -= 1; + builder.add_op(OpSwap)?; + builder.add_op(OpDrop)?; + *stack_depth -= 1; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + Ok(()) + } + ExprKind::Nullary(op) => { + match op { + NullaryOp::ActiveInputIndex => { + builder.add_op(OpTxInputIndex)?; } - if args.len() == 2 { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - compile_expr( - &args[1], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - return Ok(()); + NullaryOp::ActiveScriptPubKey => { + builder.add_op(OpTxInputIndex)?; + builder.add_op(OpTxInputSpk)?; } - match &args[0] { - Expr::String(value) => { - builder.add_data(value.as_bytes())?; - *stack_depth += 1; - Ok(()) - } - Expr::Identifier(name) => { - if let Some(Expr::String(value)) = env.get(name) { - builder.add_data(value.as_bytes())?; - *stack_depth += 1; - return Ok(()); - } - if expr_is_bytes(&args[0], env, types) { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - return Ok(()); - } - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_i64(8)?; - *stack_depth += 1; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - Ok(()) - } - _ => { - if expr_is_bytes(&args[0], env, types) { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - Ok(()) - } else { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_i64(8)?; - *stack_depth += 1; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - Ok(()) - } - } + NullaryOp::ThisScriptSize => { + let size = script_size + .ok_or_else(|| CompilerError::Unsupported("this.scriptSize is only available at compile time".to_string()))?; + builder.add_i64(size)?; + } + NullaryOp::ThisScriptSizeDataPrefix => { + let size = script_size.ok_or_else(|| { + CompilerError::Unsupported("this.scriptSizeDataPrefix is only available at compile time".to_string()) + })?; + let size: usize = size.try_into().map_err(|_| { + CompilerError::Unsupported("this.scriptSizeDataPrefix requires a non-negative script size".to_string()) + })?; + let prefix = data_prefix(size); + builder.add_data(&prefix)?; + } + NullaryOp::TxInputsLength => { + builder.add_op(OpTxInputCount)?; + } + NullaryOp::TxOutputsLength => { + builder.add_op(OpTxOutputCount)?; + } + NullaryOp::TxVersion => { + builder.add_op(OpTxVersion)?; + } + NullaryOp::TxLockTime => { + builder.add_op(OpTxLockTime)?; } } - "length" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("length() expects a single argument".to_string())); + *stack_depth += 1; + Ok(()) + } + ExprKind::Introspection { kind, index, .. } => { + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + match kind { + IntrospectionKind::InputValue => { + builder.add_op(OpTxInputAmount)?; } - if let Expr::Identifier(name) = &args[0] { - if let Some(type_name) = types.get(name) { - // Check if this is a fixed-size array type[N] (supporting constants) - if let Some(array_size) = array_size_with_constants(type_name, contract_constants) { - // Compile-time length for fixed-size arrays - builder.add_i64(array_size as i64)?; - *stack_depth += 1; - return Ok(()); - } - // Runtime length for dynamic arrays - if let Some(element_size) = array_element_size(type_name) { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_op(OpSize)?; - builder.add_op(OpSwap)?; - builder.add_op(OpDrop)?; - builder.add_i64(element_size)?; - *stack_depth += 1; - builder.add_op(OpDiv)?; - *stack_depth -= 1; - return Ok(()); - } - } + IntrospectionKind::InputScriptPubKey => { + builder.add_op(OpTxInputSpk)?; } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + IntrospectionKind::InputSigScript => { + builder.add_op(OpDup)?; + builder.add_op(OpTxInputScriptSigLen)?; + builder.add_i64(0)?; + builder.add_op(OpSwap)?; + builder.add_op(OpTxInputScriptSigSubstr)?; + } + IntrospectionKind::InputOutpointTransactionHash => { + builder.add_op(OpOutpointTxId)?; + } + IntrospectionKind::InputOutpointIndex => { + builder.add_op(OpOutpointIndex)?; + } + IntrospectionKind::InputSequenceNumber => { + builder.add_op(OpTxInputSeq)?; + } + IntrospectionKind::OutputValue => { + builder.add_op(OpTxOutputAmount)?; + } + IntrospectionKind::OutputScriptPubKey => { + builder.add_op(OpTxOutputSpk)?; + } + } + Ok(()) + } + ExprKind::DateLiteral(value) => { + builder.add_i64(*value)?; + *stack_depth += 1; + Ok(()) + } + ExprKind::NumberWithUnit { .. } => { + Err(CompilerError::Unsupported("number units must be normalized during parsing".to_string())) + } + } +} + +#[allow(clippy::too_many_arguments)] +fn compile_split_part<'i>( + source: &Expr<'i>, + index: &Expr<'i>, + part: SplitPart, + env: &HashMap>, + params: &HashMap, + types: &HashMap, + builder: &mut ScriptBuilder, + options: CompileOptions, + visiting: &mut HashSet, + stack_depth: &mut i64, + script_size: Option, + contract_constants: &HashMap>, +) -> Result<(), CompilerError> { + compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + match part { + SplitPart::Left => { + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_i64(0)?; + *stack_depth += 1; + builder.add_op(OpSwap)?; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + Ok(()) + } + SplitPart::Right => { + builder.add_op(OpSize)?; + *stack_depth += 1; + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_op(OpSwap)?; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + Ok(()) + } + } +} + +fn expr_is_bytes<'i>(expr: &Expr<'i>, env: &HashMap>, types: &HashMap) -> bool { + let mut visiting = HashSet::new(); + expr_is_bytes_inner(expr, env, types, &mut visiting) +} + +fn expr_is_bytes_inner<'i>( + expr: &Expr<'i>, + env: &HashMap>, + types: &HashMap, + visiting: &mut HashSet, +) -> bool { + match &expr.kind { + ExprKind::Byte(_) => true, + ExprKind::String(_) => true, + ExprKind::Array(values) => values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))), + ExprKind::Slice { .. } => true, + ExprKind::New { name, .. } => matches!( + name.as_str(), + "LockingBytecodeNullData" | "ScriptPubKeyP2PK" | "ScriptPubKeyP2SH" | "ScriptPubKeyP2SHFromRedeemScript" + ), + ExprKind::Call { name, .. } => { + let name = name.as_str(); + matches!( + name, + "bytes" + | "blake2b" + | "sha256" + | "OpSha256" + | "OpTxSubnetId" + | "OpTxPayloadSubstr" + | "OpOutpointTxId" + | "OpTxInputScriptSigSubstr" + | "OpTxInputSeq" + | "OpTxInputSpkSubstr" + | "OpTxOutputSpkSubstr" + | "OpInputCovenantId" + | "OpNum2Bin" + | "OpChainblockSeqCommit" + ) || name.starts_with("byte[") + } + ExprKind::Split { .. } => true, + ExprKind::Binary { op: BinaryOp::Add, left, right } => { + expr_is_bytes_inner(left, env, types, visiting) || expr_is_bytes_inner(right, env, types, visiting) + } + ExprKind::IfElse { condition: _, then_expr, else_expr } => { + expr_is_bytes_inner(then_expr, env, types, visiting) && expr_is_bytes_inner(else_expr, env, types, visiting) + } + ExprKind::Introspection { kind, .. } => matches!( + kind, + IntrospectionKind::InputScriptPubKey + | IntrospectionKind::InputSigScript + | IntrospectionKind::InputOutpointTransactionHash + | IntrospectionKind::OutputScriptPubKey + ), + ExprKind::Nullary(NullaryOp::ActiveScriptPubKey) => true, + ExprKind::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, + ExprKind::ArrayIndex { source, .. } => match &source.kind { + ExprKind::Identifier(name) => { + types.get(name).and_then(|type_name| array_element_type(type_name)).map(|element| element != "int").unwrap_or(false) + } + _ => false, + }, + ExprKind::Identifier(name) => { + if !visiting.insert(name.clone()) { + return false; + } + if let Some(expr) = env.get(name) { + let result = expr_is_bytes_inner(expr, env, types, visiting) + || types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false); + visiting.remove(name); + return result; + } + visiting.remove(name); + types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false) + } + ExprKind::UnarySuffix { kind, .. } => matches!(kind, UnarySuffixKind::Reverse), + _ => false, + } +} + +fn compile_length_expr<'i>( + expr: &Expr<'i>, + env: &HashMap>, + params: &HashMap, + types: &HashMap, + builder: &mut ScriptBuilder, + options: CompileOptions, + visiting: &mut HashSet, + stack_depth: &mut i64, + script_size: Option, + contract_constants: &HashMap>, +) -> Result<(), CompilerError> { + if let ExprKind::Identifier(name) = &expr.kind { + if let Some(type_name) = types.get(name) { + if let Some(size) = array_size_with_constants(type_name, contract_constants) { + builder.add_i64(size as i64)?; + *stack_depth += 1; + return Ok(()); + } + if let Some(element_size) = array_element_size(type_name) { + compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; builder.add_op(OpSize)?; - Ok(()) + builder.add_op(OpSwap)?; + builder.add_op(OpDrop)?; + builder.add_i64(element_size)?; + *stack_depth += 1; + builder.add_op(OpDiv)?; + *stack_depth -= 1; + return Ok(()); } - "int" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("int() expects a single argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - Ok(()) + } + } + if let ExprKind::Array(values) = &expr.kind { + builder.add_i64(values.len() as i64)?; + *stack_depth += 1; + return Ok(()); + } + compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_op(OpSize)?; + Ok(()) +} + +fn compile_call_expr<'i>( + name: &str, + args: &[Expr<'i>], + scope: &CompilationScope<'_, 'i>, + builder: &mut ScriptBuilder, + options: CompileOptions, + visiting: &mut HashSet, + stack_depth: &mut i64, + script_size: Option, + contract_constants: &HashMap>, +) -> Result<(), CompilerError> { + match name { + "OpSha256" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpSHA256, + script_size, + contract_constants, + ), + "sha256" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("sha256() expects a single argument".to_string())); } - "sig" | "pubkey" | "datasig" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - Ok(()) + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpSHA256)?; + Ok(()) + } + "OpTxSubnetId" => compile_opcode_call( + name, + args, + 0, + scope, + builder, + options, + visiting, + stack_depth, + OpTxSubnetId, + script_size, + contract_constants, + ), + "OpTxGas" => compile_opcode_call( + name, + args, + 0, + scope, + builder, + options, + visiting, + stack_depth, + OpTxGas, + script_size, + contract_constants, + ), + "OpTxPayloadLen" => compile_opcode_call( + name, + args, + 0, + scope, + builder, + options, + visiting, + stack_depth, + OpTxPayloadLen, + script_size, + contract_constants, + ), + "OpTxPayloadSubstr" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpTxPayloadSubstr, + script_size, + contract_constants, + ), + "OpOutpointTxId" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpOutpointTxId, + script_size, + contract_constants, + ), + "OpOutpointIndex" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpOutpointIndex, + script_size, + contract_constants, + ), + "OpTxInputScriptSigLen" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputScriptSigLen, + script_size, + contract_constants, + ), + "OpTxInputScriptSigSubstr" => compile_opcode_call( + name, + args, + 3, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputScriptSigSubstr, + script_size, + contract_constants, + ), + "OpTxInputSeq" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputSeq, + script_size, + contract_constants, + ), + "OpTxInputIsCoinbase" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputIsCoinbase, + script_size, + contract_constants, + ), + "OpTxInputSpkLen" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputSpkLen, + script_size, + contract_constants, + ), + "OpTxInputSpkSubstr" => compile_opcode_call( + name, + args, + 3, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputSpkSubstr, + script_size, + contract_constants, + ), + "OpTxOutputSpkLen" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxOutputSpkLen, + script_size, + contract_constants, + ), + "OpTxOutputSpkSubstr" => compile_opcode_call( + name, + args, + 3, + scope, + builder, + options, + visiting, + stack_depth, + OpTxOutputSpkSubstr, + script_size, + contract_constants, + ), + "OpAuthOutputCount" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpAuthOutputCount, + script_size, + contract_constants, + ), + "OpAuthOutputIdx" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpAuthOutputIdx, + script_size, + contract_constants, + ), + "OpInputCovenantId" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpInputCovenantId, + script_size, + contract_constants, + ), + "OpCovInputCount" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpCovInputCount, + script_size, + contract_constants, + ), + "OpCovInputIdx" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpCovInputIdx, + script_size, + contract_constants, + ), + "OpCovOutCount" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpCovOutCount, + script_size, + contract_constants, + ), + "OpCovOutputIdx" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpCovOutputIdx, + script_size, + contract_constants, + ), + "OpNum2Bin" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpNum2Bin, + script_size, + contract_constants, + ), + "OpBin2Num" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpBin2Num, + script_size, + contract_constants, + ), + "OpChainblockSeqCommit" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpChainblockSeqCommit, + script_size, + contract_constants, + ), + "bytes" => { + if args.is_empty() || args.len() > 2 { + return Err(CompilerError::Unsupported("bytes() expects one or two arguments".to_string())); + } + if args.len() == 2 { + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + compile_expr( + &args[1], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; + return Ok(()); } - name if name.starts_with("byte[") && name.ends_with(']') => { - let size_part = &name[5..name.len() - 1]; - if size_part.is_empty() { - // Handle byte[] cast (dynamic array) - just compile the argument as-is - if args.len() != 1 && args.len() != 2 { - return Err(CompilerError::Unsupported(format!("{name}() expects 1 or 2 arguments"))); + match &args[0].kind { + ExprKind::String(value) => { + builder.add_data(value.as_bytes())?; + *stack_depth += 1; + Ok(()) + } + ExprKind::Identifier(name) => { + if let Some(expr) = scope.env.get(name) { + if let ExprKind::String(value) = &expr.kind { + builder.add_data(value.as_bytes())?; + *stack_depth += 1; + return Ok(()); + } } - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - if args.len() == 2 { - // byte[](value, size) - OpNum2Bin with size parameter + if expr_is_bytes(&args[0], scope.env, scope.types) { compile_expr( - &args[1], - env, - params, - types, + &args[0], + scope.env, + scope.params, + scope.types, builder, options, visiting, @@ -3013,23 +3621,13 @@ fn compile_expr( script_size, contract_constants, )?; - *stack_depth += 1; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - } - Ok(()) - } else { - // Handle byte[N] cast - extract size from byte[N] - let size = - size_part.parse::().map_err(|_| CompilerError::Unsupported(format!("{name}() is not supported")))?; - if args.len() != 1 { - return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); + return Ok(()); } compile_expr( &args[0], - env, - params, - types, + scope.env, + scope.params, + scope.types, builder, options, visiting, @@ -3037,273 +3635,75 @@ fn compile_expr( script_size, contract_constants, )?; - builder.add_i64(size)?; + builder.add_i64(8)?; *stack_depth += 1; builder.add_op(OpNum2Bin)?; *stack_depth -= 1; Ok(()) } - } - "blake2b" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("blake2b() expects a single argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpBlake2b)?; - Ok(()) - } - "checkSig" => { - if args.len() != 2 { - return Err(CompilerError::Unsupported("checkSig() expects 2 arguments".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(&args[1], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpCheckSig)?; - *stack_depth -= 1; - Ok(()) - } - "checkDataSig" => { - // TODO: Remove this stub - for arg in args { - compile_expr(arg, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - } - for _ in 0..args.len() { - builder.add_op(OpDrop)?; - *stack_depth -= 1; - } - builder.add_op(OpTrue)?; - *stack_depth += 1; - Ok(()) - } - _ => Err(CompilerError::Unsupported(format!("unknown function call: {name}"))), - }, - Expr::New { name, args } => match name.as_str() { - "LockingBytecodeNullData" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("LockingBytecodeNullData expects a single array argument".to_string())); - } - let script = build_null_data_script(&args[0])?; - builder.add_data(&script)?; - *stack_depth += 1; - Ok(()) - } - "ScriptPubKeyP2PK" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("ScriptPubKeyP2PK expects a single pubkey argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_data(&[0x00, 0x00, OpData32])?; - *stack_depth += 1; - builder.add_op(OpSwap)?; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[OpCheckSig])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - Ok(()) - } - "ScriptPubKeyP2SH" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("ScriptPubKeyP2SH expects a single bytes32 argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_data(&[0x00, 0x00])?; - *stack_depth += 1; - builder.add_data(&[OpBlake2b])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[0x20])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_op(OpSwap)?; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[OpEqual])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - Ok(()) - } - "ScriptPubKeyP2SHFromRedeemScript" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported( - "ScriptPubKeyP2SHFromRedeemScript expects a single redeem_script argument".to_string(), - )); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpBlake2b)?; - builder.add_data(&[0x00, 0x00])?; - *stack_depth += 1; - builder.add_data(&[OpBlake2b])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[0x20])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_op(OpSwap)?; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[OpEqual])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - Ok(()) - } - _ => Err(CompilerError::Unsupported(format!("unknown constructor: {name}"))), - }, - Expr::Unary { op, expr } => { - compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - match op { - UnaryOp::Not => builder.add_op(OpNot)?, - UnaryOp::Neg => builder.add_op(OpNegate)?, - }; - Ok(()) - } - Expr::Binary { op, left, right } => { - let bytes_eq = - matches!(op, BinaryOp::Eq | BinaryOp::Ne) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); - let bytes_add = matches!(op, BinaryOp::Add) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); - if bytes_add { - compile_concat_operand( - left, - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - compile_concat_operand( - right, - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - } else { - compile_expr(left, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(right, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - } - match op { - BinaryOp::Or => { - builder.add_op(OpBoolOr)?; - } - BinaryOp::And => { - builder.add_op(OpBoolAnd)?; - } - BinaryOp::BitOr => { - builder.add_op(OpOr)?; - } - BinaryOp::BitXor => { - builder.add_op(OpXor)?; - } - BinaryOp::BitAnd => { - builder.add_op(OpAnd)?; - } - BinaryOp::Eq => { - builder.add_op(if bytes_eq { OpEqual } else { OpNumEqual })?; - } - BinaryOp::Ne => { - if bytes_eq { - builder.add_op(OpEqual)?; - builder.add_op(OpNot)?; - } else { - builder.add_op(OpNumNotEqual)?; - } - } - BinaryOp::Lt => { - builder.add_op(OpLessThan)?; - } - BinaryOp::Le => { - builder.add_op(OpLessThanOrEqual)?; - } - BinaryOp::Gt => { - builder.add_op(OpGreaterThan)?; - } - BinaryOp::Ge => { - builder.add_op(OpGreaterThanOrEqual)?; - } - BinaryOp::Add => { - if bytes_add { - builder.add_op(OpCat)?; + _ => { + if expr_is_bytes(&args[0], scope.env, scope.types) { + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + Ok(()) } else { - builder.add_op(OpAdd)?; - } - } - BinaryOp::Sub => { - builder.add_op(OpSub)?; - } - BinaryOp::Mul => { - builder.add_op(OpMul)?; - } - BinaryOp::Div => { - builder.add_op(OpDiv)?; - } - BinaryOp::Mod => { - builder.add_op(OpMod)?; - } - } - *stack_depth -= 1; - Ok(()) - } - Expr::Split { source, index, part } => { - compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - match part { - SplitPart::Left => { - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_i64(0)?; - *stack_depth += 1; - builder.add_op(OpSwap)?; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; - } - SplitPart::Right => { - builder.add_op(OpSize)?; - *stack_depth += 1; - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpSwap)?; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_i64(8)?; + *stack_depth += 1; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; + Ok(()) + } } } - Ok(()) } - Expr::ArrayIndex { source, index } => { - let resolved_source = match source.as_ref() { - Expr::Identifier(_) => source.as_ref().clone(), - _ => resolve_expr(*source.clone(), env, visiting)?, - }; - let element_type = match &resolved_source { - Expr::Identifier(name) => { - let type_name = types.get(name).or_else(|| { - env.get(name).and_then(|value| if let Expr::Identifier(inner) = value { types.get(inner) } else { None }) - }); - type_name - .and_then(|t| array_element_type(t)) - .ok_or_else(|| CompilerError::Unsupported(format!("array index requires array identifier: {name}")))? - } - _ => return Err(CompilerError::Unsupported("array index requires array identifier".to_string())), - }; - let element_size = fixed_type_size(&element_type) - .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; + "length" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("length() expects a single argument".to_string())); + } + compile_length_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + ) + } + "int" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("int() expects a single argument".to_string())); + } compile_expr( - &resolved_source, - env, - params, - types, + &args[0], + scope.env, + scope.params, + scope.types, builder, options, visiting, @@ -3311,199 +3711,181 @@ fn compile_expr( script_size, contract_constants, )?; - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_i64(element_size)?; - *stack_depth += 1; - builder.add_op(OpMul)?; - *stack_depth -= 1; - builder.add_op(OpDup)?; - *stack_depth += 1; - builder.add_i64(element_size)?; - *stack_depth += 1; - builder.add_op(OpAdd)?; - *stack_depth -= 1; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; - if element_type == "int" { - builder.add_op(OpBin2Num)?; - } Ok(()) } - Expr::Slice { source, start, end } => { - compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(start, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(end, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - - builder.add_op(Op2Dup)?; - *stack_depth += 2; - builder.add_op(OpSwap)?; - builder.add_op(OpSub)?; - *stack_depth -= 1; - builder.add_op(OpSwap)?; - builder.add_op(OpDrop)?; - *stack_depth -= 1; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; + "sig" | "pubkey" | "datasig" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); + } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; Ok(()) } - Expr::Nullary(op) => { - match op { - NullaryOp::ActiveInputIndex => { - builder.add_op(OpTxInputIndex)?; - } - NullaryOp::ActiveScriptPubKey => { - builder.add_op(OpTxInputIndex)?; - builder.add_op(OpTxInputSpk)?; - } - NullaryOp::ThisScriptSize => { - let size = script_size - .ok_or_else(|| CompilerError::Unsupported("this.scriptSize is only available at compile time".to_string()))?; - builder.add_i64(size)?; - } - NullaryOp::ThisScriptSizeDataPrefix => { - let size = script_size.ok_or_else(|| { - CompilerError::Unsupported("this.scriptSizeDataPrefix is only available at compile time".to_string()) - })?; - let size: usize = size.try_into().map_err(|_| { - CompilerError::Unsupported("this.scriptSizeDataPrefix requires a non-negative script size".to_string()) - })?; - let prefix = data_prefix(size); - builder.add_data(&prefix)?; - } - NullaryOp::TxInputsLength => { - builder.add_op(OpTxInputCount)?; - } - NullaryOp::TxOutputsLength => { - builder.add_op(OpTxOutputCount)?; - } - NullaryOp::TxVersion => { - builder.add_op(OpTxVersion)?; + name if name.starts_with("byte[") && name.ends_with(']') => { + let size_part = &name[5..name.len() - 1]; + if size_part.is_empty() { + // Handle byte[] cast (dynamic array) - just compile the argument as-is + if args.len() != 1 && args.len() != 2 { + return Err(CompilerError::Unsupported(format!("{name}() expects 1 or 2 arguments"))); + } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + if args.len() == 2 { + // byte[](value, size) - OpNum2Bin with size parameter + compile_expr( + &args[1], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + *stack_depth += 1; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; } - NullaryOp::TxLockTime => { - builder.add_op(OpTxLockTime)?; + Ok(()) + } else { + // Handle byte[N] cast - extract size from byte[N] + let size = size_part.parse::().map_err(|_| CompilerError::Unsupported(format!("{name}() is not supported")))?; + if args.len() != 1 { + return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_i64(size)?; + *stack_depth += 1; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; + Ok(()) } - *stack_depth += 1; - Ok(()) } - Expr::Introspection { kind, index } => { - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - match kind { - IntrospectionKind::InputValue => { - builder.add_op(OpTxInputAmount)?; - } - IntrospectionKind::InputScriptPubKey => { - builder.add_op(OpTxInputSpk)?; - } - IntrospectionKind::InputSigScript => { - builder.add_op(OpDup)?; - builder.add_op(OpTxInputScriptSigLen)?; - builder.add_i64(0)?; - builder.add_op(OpSwap)?; - builder.add_op(OpTxInputScriptSigSubstr)?; - } - IntrospectionKind::OutputValue => { - builder.add_op(OpTxOutputAmount)?; - } - IntrospectionKind::OutputScriptPubKey => { - builder.add_op(OpTxOutputSpk)?; - } + "blake2b" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("blake2b() expects a single argument".to_string())); } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpBlake2b)?; Ok(()) } - } -} - -fn expr_is_bytes(expr: &Expr, env: &HashMap, types: &HashMap) -> bool { - let mut visiting = HashSet::new(); - expr_is_bytes_inner(expr, env, types, &mut visiting) -} - -fn expr_is_bytes_inner( - expr: &Expr, - env: &HashMap, - types: &HashMap, - visiting: &mut HashSet, -) -> bool { - match expr { - Expr::Byte(_) => true, - Expr::Array(values) => is_byte_array(&Expr::Array(values.clone())), - Expr::StateObject(_) => false, - Expr::String(_) => true, - Expr::Slice { .. } => true, - Expr::New { name, .. } => matches!( - name.as_str(), - "LockingBytecodeNullData" | "ScriptPubKeyP2PK" | "ScriptPubKeyP2SH" | "ScriptPubKeyP2SHFromRedeemScript" - ), - Expr::Call { name, .. } => { - matches!( - name.as_str(), - "blake2b" - | "sha256" - | "OpSha256" - | "OpTxSubnetId" - | "OpTxPayloadSubstr" - | "OpOutpointTxId" - | "OpTxInputScriptSigSubstr" - | "OpTxInputSeq" - | "OpTxInputSpkSubstr" - | "OpTxOutputSpkSubstr" - | "OpInputCovenantId" - | "OpNum2Bin" - | "OpChainblockSeqCommit" - ) || name.starts_with("byte[") - } - Expr::Split { .. } => true, - Expr::Binary { op: BinaryOp::Add, left, right } => { - expr_is_bytes_inner(left, env, types, visiting) || expr_is_bytes_inner(right, env, types, visiting) - } - Expr::IfElse { condition: _, then_expr, else_expr } => { - expr_is_bytes_inner(then_expr, env, types, visiting) && expr_is_bytes_inner(else_expr, env, types, visiting) - } - Expr::Introspection { kind, .. } => { - matches!( - kind, - IntrospectionKind::InputScriptPubKey | IntrospectionKind::InputSigScript | IntrospectionKind::OutputScriptPubKey - ) - } - Expr::Nullary(NullaryOp::ActiveScriptPubKey) => true, - Expr::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, - Expr::ArrayIndex { source, .. } => match source.as_ref() { - Expr::Identifier(name) => { - types.get(name).and_then(|type_name| array_element_type(type_name)).map(|element| element != "int").unwrap_or(false) + "checkSig" => { + if args.len() != 2 { + return Err(CompilerError::Unsupported("checkSig() expects 2 arguments".to_string())); } - _ => false, - }, - Expr::Identifier(name) => { - if !visiting.insert(name.clone()) { - return false; + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + compile_expr( + &args[1], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpCheckSig)?; + *stack_depth -= 1; + Ok(()) + } + "checkDataSig" => { + // TODO: Remove this stub + for arg in args { + compile_expr( + arg, + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; } - if let Some(expr) = env.get(name) { - let result = expr_is_bytes_inner(expr, env, types, visiting) - || types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false); - visiting.remove(name); - return result; + for _ in 0..args.len() { + builder.add_op(OpDrop)?; + *stack_depth -= 1; } - visiting.remove(name); - types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false) + builder.add_op(OpTrue)?; + *stack_depth += 1; + Ok(()) } - _ => false, + _ => Err(CompilerError::Unsupported(format!("unknown function call: {name}"))), } } #[allow(clippy::too_many_arguments)] -fn compile_opcode_call( +fn compile_opcode_call<'i>( name: &str, - args: &[Expr], + args: &[Expr<'i>], expected_args: usize, - scope: &CompilationScope, + scope: &CompilationScope<'_, 'i>, builder: &mut ScriptBuilder, options: CompileOptions, visiting: &mut HashSet, stack_depth: &mut i64, opcode: u8, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { if args.len() != expected_args { return Err(CompilerError::Unsupported(format!("{name}() expects {expected_args} argument(s)"))); @@ -3527,9 +3909,9 @@ fn compile_opcode_call( Ok(()) } -fn compile_concat_operand( - expr: &Expr, - env: &HashMap, +fn compile_concat_operand<'i>( + expr: &Expr<'i>, + env: &HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, @@ -3537,7 +3919,7 @@ fn compile_concat_operand( visiting: &mut HashSet, stack_depth: &mut i64, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; if !expr_is_bytes(expr, env, types) { @@ -3562,35 +3944,40 @@ fn is_bytes_type(type_name: &str) -> bool { is_array_type(type_name) } -fn build_null_data_script(arg: &Expr) -> Result, CompilerError> { - let elements = match arg { - Expr::Array(items) => items, +fn build_null_data_script<'i>(arg: &Expr<'i>) -> Result, CompilerError> { + let elements = match &arg.kind { + ExprKind::Array(items) => items, _ => return Err(CompilerError::Unsupported("LockingBytecodeNullData expects an array literal".to_string())), }; let mut builder = ScriptBuilder::new(); builder.add_op(OpReturn)?; for item in elements { - match item { - Expr::Int(value) => { + match &item.kind { + ExprKind::Int(value) => { + builder.add_i64(*value)?; + } + ExprKind::DateLiteral(value) => { builder.add_i64(*value)?; } - Expr::Array(values) if is_byte_array(&Expr::Array(values.clone())) => { - // Handle byte arrays - let bytes: Vec = values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); + ExprKind::Array(values) if values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))) => { + let bytes: Vec = values + .iter() + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) + .collect(); builder.add_data(&bytes)?; } - Expr::String(value) => { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; } - Expr::Call { name, args } if name == "byte[]" => { + ExprKind::Call { name, args, .. } if name == "bytes" || name == "byte[]" => { if args.len() != 1 { return Err(CompilerError::Unsupported( "byte[]() in LockingBytecodeNullData expects a single argument".to_string(), )); } - match &args[0] { - Expr::String(value) => { + match &args[0].kind { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; } _ => { @@ -3600,7 +3987,9 @@ fn build_null_data_script(arg: &Expr) -> Result, CompilerError> { } } } - _ => return Err(CompilerError::Unsupported("LockingBytecodeNullData only supports int or bytes literals".to_string())), + _ => { + return Err(CompilerError::Unsupported("LockingBytecodeNullData only supports int or bytes literals".to_string())); + } } } @@ -3611,14 +4000,6 @@ fn build_null_data_script(arg: &Expr) -> Result, CompilerError> { Ok(spk_bytes) } -fn parse_date_value(value: &str) -> Result { - let timestamp = NaiveDateTime::parse_from_str(value, "%Y-%m-%dT%H:%M:%S") - .map_err(|_| CompilerError::InvalidLiteral("invalid date literal".to_string()))? - .and_utc() - .timestamp(); - Ok(timestamp) -} - fn data_prefix(data_len: usize) -> Vec { let dummy_data = vec![0u8; data_len]; let mut builder = ScriptBuilder::new(); diff --git a/silverscript-lang/src/compiler/debug_recording.rs b/silverscript-lang/src/compiler/debug_recording.rs index badda453..ff84dd62 100644 --- a/silverscript-lang/src/compiler/debug_recording.rs +++ b/silverscript-lang/src/compiler/debug_recording.rs @@ -10,11 +10,11 @@ use crate::debug::{ use super::{CompilerError, resolve_expr_for_debug}; -type ResolvedVariableUpdate = (String, String, Expr); +type ResolvedVariableUpdate<'i> = (String, String, Expr<'i>); -pub(super) fn record_synthetic_range( +pub(super) fn record_synthetic_range<'i>( builder: &mut ScriptBuilder, - recorder: &mut DebugSink, + recorder: &mut DebugSink<'i>, label: &'static str, f: impl FnOnce(&mut ScriptBuilder) -> Result<(), CompilerError>, ) -> Result<(), CompilerError> { @@ -28,11 +28,11 @@ pub(super) fn record_synthetic_range( /// Per-function debug recorder active during function compilation. /// Records params, statements, and variable updates for a single function. #[derive(Debug, Default)] -pub struct FunctionDebugRecorder { +pub struct FunctionDebugRecorder<'i> { function_name: String, enabled: bool, events: Vec, - variable_updates: Vec, + variable_updates: Vec>, param_mappings: Vec, next_seq: u32, call_depth: u32, @@ -40,8 +40,8 @@ pub struct FunctionDebugRecorder { next_frame_id: u32, } -impl FunctionDebugRecorder { - pub fn new(enabled: bool, function: &FunctionAst, contract_fields: &[ContractFieldAst]) -> Self { +impl<'i> FunctionDebugRecorder<'i> { + pub fn new(enabled: bool, function: &FunctionAst<'i>, contract_fields: &[ContractFieldAst<'i>]) -> Self { let mut recorder = Self { function_name: function.name.clone(), enabled, call_depth: 0, frame_id: 0, next_frame_id: 1, ..Default::default() }; recorder.record_stack_bindings(function, contract_fields); @@ -101,7 +101,7 @@ impl FunctionDebugRecorder { Some(sequence) } - fn record_stack_bindings(&mut self, function: &FunctionAst, contract_fields: &[ContractFieldAst]) { + fn record_stack_bindings(&mut self, function: &FunctionAst<'i>, contract_fields: &[ContractFieldAst<'i>]) { if !self.enabled { return; } @@ -129,20 +129,21 @@ impl FunctionDebugRecorder { } } - fn record_statement_span(&mut self, span: Option, bytecode_start: usize, bytecode_len: usize) -> Option { + fn record_statement_span(&mut self, span: SourceSpan, bytecode_start: usize, bytecode_len: usize) -> Option { let kind = if bytecode_len == 0 { DebugEventKind::Virtual {} } else { DebugEventKind::Statement {} }; - self.push_event(bytecode_start, bytecode_start + bytecode_len, span, kind) + self.push_event(bytecode_start, bytecode_start + bytecode_len, Some(span), kind) } fn record_statement_updates( &mut self, - stmt: &Statement, + stmt: &Statement<'i>, bytecode_start: usize, bytecode_end: usize, - variables: Vec, + variables: Vec>, ) { - if let Some(sequence) = self.record_statement_span(stmt.span, bytecode_start, bytecode_end.saturating_sub(bytecode_start)) { - self.record_variable_updates(variables, bytecode_end, stmt.span, sequence); + let span = SourceSpan::from(stmt.span()); + if let Some(sequence) = self.record_statement_span(span, bytecode_start, bytecode_end.saturating_sub(bytecode_start)) { + self.record_variable_updates(variables, bytecode_end, Some(span), sequence); } } @@ -152,11 +153,11 @@ impl FunctionDebugRecorder { /// evaluation can compute values from the current state. pub fn record_statement_with_env_diff( &mut self, - stmt: &Statement, + stmt: &Statement<'i>, bytecode_start: usize, bytecode_end: usize, - before_env: Option<&HashMap>, - after_env: &HashMap, + before_env: Option<&HashMap>>, + after_env: &HashMap>, types: &HashMap, ) -> Result<(), CompilerError> { let updates = self.collect_variable_updates(before_env, after_env, types)?; @@ -169,8 +170,8 @@ impl FunctionDebugRecorder { /// without adding an extra source step at the call-site. pub fn record_inline_param_updates( &mut self, - function: &FunctionAst, - env: &HashMap, + function: &FunctionAst<'i>, + env: &HashMap>, span: Option, bytecode_offset: usize, ) -> Result<(), CompilerError> { @@ -180,7 +181,6 @@ impl FunctionDebugRecorder { // Anchor inline param updates to the next callee statement sequence. // We intentionally "peek" (do not consume) so these updates align with // the first real callee statement event sequence. - // without creating an extra steppable mapping at the call-site span. let sequence = self.next_seq; let mut variables = Vec::new(); for param in &function.params { @@ -189,7 +189,7 @@ impl FunctionDebugRecorder { &mut variables, ¶m.name, ¶m.type_ref.type_name(), - env.get(¶m.name).cloned().unwrap_or_else(|| Expr::Identifier(param.name.clone())), + env.get(¶m.name).cloned().unwrap_or_else(|| Expr::identifier(param.name.clone())), )?; } self.record_variable_updates(variables, bytecode_offset, span, sequence); @@ -209,13 +209,13 @@ impl FunctionDebugRecorder { span: Option, bytecode_offset: usize, callee: &str, - inline: &FunctionDebugRecorder, + inline: &FunctionDebugRecorder<'i>, ) { self.merge_inline_events(inline); self.push_event(bytecode_offset, bytecode_offset, span, DebugEventKind::InlineCallExit { callee: callee.to_string() }); } - fn merge_inline_events(&mut self, inline: &FunctionDebugRecorder) { + fn merge_inline_events(&mut self, inline: &FunctionDebugRecorder<'i>) { if !self.enabled || inline.events.is_empty() { // Keep frame-id frontier monotonic even if the inline call recorded // no events; this preserves uniqueness for later sibling calls. @@ -249,7 +249,7 @@ impl FunctionDebugRecorder { fn record_variable_updates( &mut self, - variables: Vec, + variables: Vec>, bytecode_offset: usize, span: Option, sequence: u32, @@ -273,10 +273,10 @@ impl FunctionDebugRecorder { fn collect_variable_updates( &self, - before_env: Option<&HashMap>, - after_env: &HashMap, + before_env: Option<&HashMap>>, + after_env: &HashMap>, types: &HashMap, - ) -> Result, CompilerError> { + ) -> Result>, CompilerError> { if !self.enabled { return Ok(Vec::new()); } @@ -311,14 +311,13 @@ impl FunctionDebugRecorder { /// Records a variable update by resolving its expression against the current environment. /// This expands locals and synthetic inline placeholders (`__arg_*`) into /// caller-visible expressions, leaving only real param identifiers. - /// The resolved expression is what enables shadow VM evaluation at debug time. fn variable_update( &self, - env: &HashMap, - variables: &mut Vec, + env: &HashMap>, + variables: &mut Vec>, name: &str, type_name: &str, - expr: Expr, + expr: Expr<'i>, ) -> Result<(), CompilerError> { if !self.enabled { return Ok(()); @@ -331,24 +330,24 @@ impl FunctionDebugRecorder { /// Global debug recording sink that can be enabled or disabled. /// When Off, all recording calls become no-ops with zero overhead. -pub enum DebugSink { +pub enum DebugSink<'i> { Off, - On(DebugRecorder), + On(DebugRecorder<'i>), } -impl DebugSink { +impl<'i> DebugSink<'i> { pub fn new(enabled: bool) -> Self { if enabled { Self::On(DebugRecorder::default()) } else { Self::Off } } - fn recorder_mut(&mut self) -> Option<&mut DebugRecorder> { + fn recorder_mut(&mut self) -> Option<&mut DebugRecorder<'i>> { match self { Self::Off => None, Self::On(rec) => Some(rec), } } - pub fn record_constructor_constants(&mut self, params: &[ParamAst], values: &[Expr]) { + pub fn record_constructor_constants(&mut self, params: &[ParamAst<'i>], values: &[Expr<'i>]) { let Some(rec) = self.recorder_mut() else { return; }; @@ -380,7 +379,13 @@ impl DebugSink { }); } - pub fn record_compiled_function(&mut self, name: &str, script_len: usize, debug: &FunctionDebugRecorder, offset: usize) { + pub fn record_compiled_function( + &mut self, + name: &str, + script_len: usize, + debug: &FunctionDebugRecorder<'i>, + offset: usize, + ) { let Some(rec) = self.recorder_mut() else { return; }; @@ -391,7 +396,7 @@ impl DebugSink { record_param_mappings(&debug.param_mappings, rec); } - pub fn into_debug_info(self, source: String) -> Option { + pub fn into_debug_info(self, source: String) -> Option> { match self { Self::Off => None, Self::On(rec) => Some(rec.into_debug_info(source)), @@ -399,7 +404,7 @@ impl DebugSink { } } -fn emit_events_with_offset(events: &[DebugEvent], offset: usize, seq_base: u32, recorder: &mut DebugRecorder) { +fn emit_events_with_offset(events: &[DebugEvent], offset: usize, seq_base: u32, recorder: &mut DebugRecorder<'_>) { for event in events { recorder.record(DebugEvent { bytecode_start: event.bytecode_start + offset, @@ -413,7 +418,12 @@ fn emit_events_with_offset(events: &[DebugEvent], offset: usize, seq_base: u32, } } -fn emit_variable_updates_with_offset(updates: &[DebugVariableUpdate], offset: usize, seq_base: u32, recorder: &mut DebugRecorder) { +fn emit_variable_updates_with_offset<'i>( + updates: &[DebugVariableUpdate<'i>], + offset: usize, + seq_base: u32, + recorder: &mut DebugRecorder<'i>, +) { for update in updates { recorder.record_variable_update(DebugVariableUpdate { name: update.name.clone(), @@ -428,7 +438,7 @@ fn emit_variable_updates_with_offset(updates: &[DebugVariableUpdate], offset: us } } -fn record_param_mappings(params: &[DebugParamMapping], recorder: &mut DebugRecorder) { +fn record_param_mappings(params: &[DebugParamMapping], recorder: &mut DebugRecorder<'_>) { for param in params { recorder.record_param(param.clone()); } diff --git a/silverscript-lang/src/debug.rs b/silverscript-lang/src/debug.rs index a30972f0..020ed760 100644 --- a/silverscript-lang/src/debug.rs +++ b/silverscript-lang/src/debug.rs @@ -1,6 +1,6 @@ use crate::ast::Expr; -use pest::Span; use serde::{Deserialize, Serialize}; +use crate::span; pub mod presentation; pub mod session; @@ -13,8 +13,8 @@ pub struct SourceSpan { pub end_col: u32, } -impl<'a> From> for SourceSpan { - fn from(span: Span<'a>) -> Self { +impl<'a> From> for SourceSpan { + fn from(span: span::Span<'a>) -> Self { let (line, col) = span.start_pos().line_col(); let (end_line, end_col) = span.end_pos().line_col(); Self { line: line as u32, col: col as u32, end_line: end_line as u32, end_col: end_col as u32 } @@ -63,21 +63,21 @@ pub struct DebugEvent { /// Collects events, variable updates, param mappings, function ranges, and constants. /// Converted to `DebugInfo` after compilation completes. #[derive(Debug, Default)] -pub struct DebugRecorder { +pub struct DebugRecorder<'i> { events: Vec, - variable_updates: Vec, + variable_updates: Vec>, params: Vec, functions: Vec, - constants: Vec, + constants: Vec>, next_sequence: u32, } -impl DebugRecorder { +impl<'i> DebugRecorder<'i> { pub fn record(&mut self, event: DebugEvent) { self.events.push(event); } - pub fn record_variable_update(&mut self, update: DebugVariableUpdate) { + pub fn record_variable_update(&mut self, update: DebugVariableUpdate<'i>) { self.variable_updates.push(update); } @@ -89,7 +89,7 @@ impl DebugRecorder { self.functions.push(function); } - pub fn record_constant(&mut self, constant: DebugConstantMapping) { + pub fn record_constant(&mut self, constant: DebugConstantMapping<'i>) { self.constants.push(constant); } @@ -113,7 +113,7 @@ impl DebugRecorder { self.events } - pub fn into_debug_info(self, source: String) -> DebugInfo { + pub fn into_debug_info(self, source: String) -> DebugInfo<'i> { DebugInfo { source, mappings: self.events.into_iter().map(DebugMapping::from).collect(), @@ -128,16 +128,16 @@ impl DebugRecorder { /// Complete debug metadata attached to compiled contract. /// Contains everything needed to map bytecode execution back to source and evaluate variables. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DebugInfo { +pub struct DebugInfo<'i> { pub source: String, pub mappings: Vec, - pub variable_updates: Vec, + pub variable_updates: Vec>, pub params: Vec, pub functions: Vec, - pub constants: Vec, + pub constants: Vec>, } -impl DebugInfo { +impl<'i> DebugInfo<'i> { pub fn empty() -> Self { Self { source: String::new(), @@ -151,12 +151,12 @@ impl DebugInfo { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DebugVariableUpdate { +pub struct DebugVariableUpdate<'i> { pub name: String, pub type_name: String, /// Pre-resolved expression with all local variable references expanded inline. /// Only function parameter Identifiers remain. Enables shadow VM evaluation. - pub expr: Expr, + pub expr: Expr<'i>, pub bytecode_offset: usize, pub span: Option, pub function: String, @@ -190,10 +190,10 @@ pub struct DebugFunctionRange { /// Constructor constant (contract instantiation parameter). /// Recorded for display in debugger variable list. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DebugConstantMapping { +pub struct DebugConstantMapping<'i> { pub name: String, pub type_name: String, - pub value: Expr, + pub value: Expr<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/silverscript-lang/src/debug/session.rs b/silverscript-lang/src/debug/session.rs index 5365dec0..780613b1 100644 --- a/silverscript-lang/src/debug/session.rs +++ b/silverscript-lang/src/debug/session.rs @@ -7,7 +7,7 @@ use kaspa_txscript::script_builder::ScriptBuilder; use kaspa_txscript::{DynOpcodeImplementation, EngineCtx, EngineFlags, TxScriptEngine, parse_script}; use serde::{Deserialize, Serialize}; -use crate::ast::Expr; +use crate::ast::{Expr, ExprKind}; use crate::compiler::compile_debug_expr; use crate::debug::presentation::{build_source_context, format_value as format_debug_value}; use crate::debug::{DebugFunctionRange, DebugInfo, DebugMapping, DebugParamMapping, DebugVariableUpdate, MappingKind, SourceSpan}; @@ -78,14 +78,14 @@ pub struct OpcodeMeta { pub mapping: Option, } -pub struct DebugSession<'a> { +pub struct DebugSession<'a, 'i> { engine: DebugEngine<'a>, opcodes: Vec>>, op_displays: Vec, opcode_offsets: Vec, script_len: usize, pc: usize, - debug_info: DebugInfo, + debug_info: DebugInfo<'i>, source_mappings: Vec, current_step_index: Option, source_lines: Vec, @@ -108,7 +108,7 @@ struct VariableContext<'a> { frame_id: u32, } -impl<'a> DebugSession<'a> { +impl<'a, 'i> DebugSession<'a, 'i> { // --- Session construction + stepping --- /// Creates a debug session for lockscript-only execution. @@ -116,7 +116,7 @@ impl<'a> DebugSession<'a> { pub fn lockscript_only( script: &[u8], source: &str, - debug_info: Option, + debug_info: Option>, engine: DebugEngine<'a>, ) -> Result { Self::from_scripts(script, source, debug_info, engine) @@ -128,7 +128,7 @@ impl<'a> DebugSession<'a> { sigscript: &[u8], lockscript: &[u8], source: &str, - debug_info: Option, + debug_info: Option>, mut engine: DebugEngine<'a>, ) -> Result { seed_engine_with_sigscript(&mut engine, sigscript)?; @@ -139,7 +139,7 @@ impl<'a> DebugSession<'a> { pub fn from_scripts( script: &[u8], source: &str, - debug_info: Option, + debug_info: Option>, engine: DebugEngine<'a>, ) -> Result { let debug_info = debug_info.unwrap_or_else(DebugInfo::empty); @@ -364,7 +364,7 @@ impl<'a> DebugSession<'a> { self.op_displays.len() } - pub fn debug_info(&self) -> &DebugInfo { + pub fn debug_info(&self) -> &DebugInfo<'i> { &self.debug_info } @@ -486,8 +486,8 @@ impl<'a> DebugSession<'a> { offset: usize, sequence: u32, frame_id: u32, - ) -> HashMap { - let mut latest: HashMap = HashMap::new(); + ) -> HashMap> { + let mut latest: HashMap> = HashMap::new(); for update in self .debug_info .variable_updates @@ -567,7 +567,7 @@ impl<'a> DebugSession<'a> { fn update_is_visible( &self, - update: &DebugVariableUpdate, + update: &DebugVariableUpdate<'i>, function_name: &str, offset: usize, sequence: u32, @@ -673,7 +673,11 @@ impl<'a> DebugSession<'a> { stacks.dstack.iter().map(|item| encode_hex(item)).collect() } - fn evaluate_update_with_shadow_vm(&self, function_name: &str, update: &DebugVariableUpdate) -> Result { + fn evaluate_update_with_shadow_vm( + &self, + function_name: &str, + update: &DebugVariableUpdate<'i>, + ) -> Result { self.evaluate_expr_with_shadow_vm(function_name, &update.type_name, &update.expr) } @@ -683,7 +687,12 @@ impl<'a> DebugSession<'a> { /// that pushes current param values then executes the bytecode, run on fresh VM, /// read result from top of stack. This guarantees debugger sees same semantics as /// real execution without duplicating evaluation logic. - fn evaluate_expr_with_shadow_vm(&self, function_name: &str, type_name: &str, expr: &Expr) -> Result { + fn evaluate_expr_with_shadow_vm( + &self, + function_name: &str, + type_name: &str, + expr: &Expr<'i>, + ) -> Result { let params = self.shadow_param_values(function_name)?; let mut param_indexes = HashMap::new(); let mut param_types = HashMap::new(); @@ -739,12 +748,12 @@ impl<'a> DebugSession<'a> { decode_value_by_type(¶m.type_name, bytes) } - fn evaluate_constant(&self, expr: &Expr) -> DebugValue { - match expr { - Expr::Int(v) => DebugValue::Int(*v), - Expr::Bool(v) => DebugValue::Bool(*v), - Expr::Byte(v) => DebugValue::Bytes(vec![*v]), - Expr::String(v) => DebugValue::String(v.clone()), + fn evaluate_constant(&self, expr: &Expr<'i>) -> DebugValue { + match &expr.kind { + ExprKind::Int(v) => DebugValue::Int(*v), + ExprKind::Bool(v) => DebugValue::Bool(*v), + ExprKind::Byte(v) => DebugValue::Bytes(vec![*v]), + ExprKind::String(v) => DebugValue::String(v.clone()), _ => DebugValue::Unknown("complex expression".to_string()), } } @@ -847,14 +856,15 @@ fn encode_hex(bytes: &[u8]) -> String { mod tests { use super::*; - use crate::ast::{BinaryOp, Expr}; + use crate::ast::{BinaryOp, Expr, ExprKind}; use crate::debug::{DebugConstantMapping, DebugFunctionRange, DebugInfo, DebugParamMapping, DebugVariableUpdate}; + use crate::span; fn make_session( params: Vec, - updates: Vec, + updates: Vec>, sigscript: &[u8], - ) -> Result, kaspa_txscript_errors::TxScriptError> { + ) -> Result, kaspa_txscript_errors::TxScriptError> { let sig_cache = Box::leak(Box::new(Cache::new(10_000))); let reused_values: &'static SigHashReusedValuesUnsync = Box::leak(Box::new(SigHashReusedValuesUnsync::new())); let engine: DebugEngine<'static> = @@ -865,7 +875,7 @@ mod tests { variable_updates: updates, params, functions: vec![DebugFunctionRange { name: "f".to_string(), bytecode_start: 0, bytecode_end: 1 }], - constants: vec![DebugConstantMapping { name: "K".to_string(), type_name: "int".to_string(), value: Expr::Int(7) }], + constants: vec![DebugConstantMapping { name: "K".to_string(), type_name: "int".to_string(), value: Expr::int(7) }], }; DebugSession::full(sigscript, &[], "", Some(debug_info), engine) } @@ -899,11 +909,11 @@ mod tests { .evaluate_expr_with_shadow_vm( "f", "int", - &Expr::Binary { + &Expr::new(ExprKind::Binary { op: BinaryOp::Add, - left: Box::new(Expr::Identifier("a".to_string())), - right: Box::new(Expr::Identifier("b".to_string())), - }, + left: Box::new(Expr::identifier("a")), + right: Box::new(Expr::identifier("b")), + }, span::Span::default()), ) .unwrap(); assert!(matches!(value, DebugValue::Int(12))); @@ -920,7 +930,7 @@ mod tests { vec![DebugVariableUpdate { name: "x".to_string(), type_name: "int".to_string(), - expr: Expr::Identifier("missing".to_string()), + expr: Expr::identifier("missing"), bytecode_offset: 0, span: None, function: "f".to_string(), diff --git a/silverscript-lang/src/diagnostic/mod.rs b/silverscript-lang/src/diagnostic/mod.rs new file mode 100644 index 00000000..88e1e5b4 --- /dev/null +++ b/silverscript-lang/src/diagnostic/mod.rs @@ -0,0 +1,5 @@ +mod parse; +mod parse_diagnostics; + +pub use parse::{ErrorSpan, ParseDiagnostic, ParseDiagnosticLabel, ParseDisplayLocation, ParseErrorInterpretation}; +pub(crate) use parse_diagnostics::interpret_parse_error; diff --git a/silverscript-lang/src/diagnostic/parse.rs b/silverscript-lang/src/diagnostic/parse.rs new file mode 100644 index 00000000..731a0551 --- /dev/null +++ b/silverscript-lang/src/diagnostic/parse.rs @@ -0,0 +1,217 @@ +use std::fmt; + +use pest::Position; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ErrorSpan { + pub start: usize, + pub end: usize, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum ParseErrorInterpretation { + MissingSemicolon, + Unclassified, +} + +impl ParseErrorInterpretation { + pub const fn code(self) -> &'static str { + match self { + Self::MissingSemicolon => "missing_semicolon", + Self::Unclassified => "parse_error", + } + } + + pub fn from_code(code: &str) -> Option { + match code { + "missing_semicolon" => Some(Self::MissingSemicolon), + "parse_error" => Some(Self::Unclassified), + _ => None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseDiagnosticLabel { + span: ErrorSpan, + message: String, +} + +impl ParseDiagnosticLabel { + pub fn new(span: ErrorSpan, message: impl Into) -> Self { + Self { span, message: message.into() } + } + + pub fn span(&self) -> ErrorSpan { + self.span + } + + pub fn message(&self) -> &str { + &self.message + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseDisplayLocation { + line: usize, + column: usize, + line_text: String, +} + +impl ParseDisplayLocation { + pub fn new(line: usize, column: usize, line_text: impl Into) -> Self { + Self { line, column, line_text: line_text.into() } + } + + pub fn line(&self) -> usize { + self.line + } + + pub fn column(&self) -> usize { + self.column + } + + pub fn line_text(&self) -> &str { + &self.line_text + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseDiagnostic { + interpretation: ParseErrorInterpretation, + span: ErrorSpan, + primary_message: String, + expected_tokens: Vec, + labels: Vec, + help: Option, + notes: Vec, + source_text: Box, +} + +impl ParseDiagnostic { + pub(crate) fn new( + interpretation: ParseErrorInterpretation, + span: ErrorSpan, + source_text: &str, + primary_message: impl Into, + ) -> Self { + Self { + interpretation, + span, + primary_message: primary_message.into(), + expected_tokens: Vec::new(), + labels: Vec::new(), + help: None, + notes: Vec::new(), + source_text: source_text.to_owned().into_boxed_str(), + } + } + + pub(crate) fn with_expected_tokens(mut self, expected_tokens: Vec) -> Self { + self.expected_tokens = expected_tokens; + self + } + + pub(crate) fn with_labels(mut self, labels: Vec) -> Self { + self.labels = labels; + self + } + + pub(crate) fn with_help(mut self, help: impl Into) -> Self { + self.help = Some(help.into()); + self + } + + pub(crate) fn with_notes(mut self, notes: Vec) -> Self { + self.notes = notes; + self + } + + pub fn code(&self) -> &'static str { + self.interpretation.code() + } + + pub fn interpretation(&self) -> ParseErrorInterpretation { + self.interpretation + } + + pub fn span(&self) -> ErrorSpan { + self.span + } + + pub fn primary_message(&self) -> &str { + &self.primary_message + } + + pub fn expected_tokens(&self) -> &[String] { + &self.expected_tokens + } + + pub fn labels(&self) -> &[ParseDiagnosticLabel] { + &self.labels + } + + pub fn help(&self) -> Option<&str> { + self.help.as_deref() + } + + pub fn notes(&self) -> &[String] { + &self.notes + } + + pub fn source_text(&self) -> &str { + &self.source_text + } + + pub fn display_location(&self) -> ParseDisplayLocation { + if self.source_text.is_empty() { + return ParseDisplayLocation::new(1, 1, String::new()); + } + let pos = self.span.start.min(self.source_text.len()); + let position = Position::new(&self.source_text, pos).unwrap_or_else(|| Position::from_start(&self.source_text)); + let (line, column) = position.line_col(); + let line_text = position.line_of().lines().next().unwrap_or_default().to_owned(); + ParseDisplayLocation::new(line, column, line_text) + } +} + +// TODO: make the display dumb and: +// * CLI: adapt diagnostic to miette diagnostic +// * LSP: adapt to LSP diagnostic (tower-lsp) +impl fmt::Display for ParseDiagnostic { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let location = self.display_location(); + let line_digits = location.line().to_string().len(); + let spacing = " ".repeat(line_digits); + let underline_pad = " ".repeat(location.column().saturating_sub(1)); + writeln!(f, "{spacing}--> {}:{}", location.line(), location.column())?; + writeln!(f, "{spacing} |")?; + writeln!(f, "{} | {}", location.line(), location.line_text())?; + writeln!(f, "{spacing} | {underline_pad}^---")?; + writeln!(f, "{spacing} |")?; + writeln!(f, "{spacing} = error: {}", self.primary_message)?; + + if !self.expected_tokens.is_empty() { + let expected_tokens = self.expected_tokens.iter().map(|token| format_expected_token(token)).collect::>().join(", "); + writeln!(f, "{spacing} note: expected one of tokens: {expected_tokens}")?; + } + for note in &self.notes { + writeln!(f, "{spacing} note: {note}")?; + } + if let Some(help) = &self.help { + writeln!(f, "{spacing} help: {help}")?; + } + + Ok(()) + } +} + +fn format_expected_token(token: &str) -> String { + match token { + "WHITESPACE" => "WHITESPACE".to_owned(), + _ => format!("`{token}`"), + } +} + +impl std::error::Error for ParseDiagnostic {} diff --git a/silverscript-lang/src/diagnostic/parse_diagnostics.rs b/silverscript-lang/src/diagnostic/parse_diagnostics.rs new file mode 100644 index 00000000..e24aa641 --- /dev/null +++ b/silverscript-lang/src/diagnostic/parse_diagnostics.rs @@ -0,0 +1,178 @@ +use std::collections::BTreeSet; + +use super::parse::{ErrorSpan, ParseDiagnostic, ParseDiagnosticLabel, ParseErrorInterpretation}; +use crate::parser::Rule; + +const MISSING_SEMICOLON_EXPECTED_TOKENS: &[&str] = &["WHITESPACE", "/*", "//", ";"]; + +#[derive(Clone, Copy)] +enum SpanStrategy { + AtFailure, + PreviousNonWhitespaceOrFailure, +} + +impl SpanStrategy { + fn resolve(self, input: &str, failure_pos: usize) -> ErrorSpan { + let failure_pos = failure_pos.min(input.len()); + let start = match self { + Self::AtFailure => failure_pos, + Self::PreviousNonWhitespaceOrFailure => focused_error_start(input, failure_pos), + }; + ErrorSpan { start, end: start } + } +} + +#[derive(Clone, Copy)] +struct InterpretationSpec { + interpretation: ParseErrorInterpretation, + span_strategy: SpanStrategy, + expected_tokens_override: Option<&'static [&'static str]>, + help: Option<&'static str>, + primary_label: Option<&'static str>, + notes: &'static [&'static str], +} + +const UNCLASSIFIED_SPEC: InterpretationSpec = InterpretationSpec { + interpretation: ParseErrorInterpretation::Unclassified, + span_strategy: SpanStrategy::AtFailure, + expected_tokens_override: None, + help: None, + primary_label: None, + notes: &[], +}; + +const INTERPRETATION_SPECS: &[InterpretationSpec] = &[ + InterpretationSpec { + interpretation: ParseErrorInterpretation::MissingSemicolon, + span_strategy: SpanStrategy::PreviousNonWhitespaceOrFailure, + expected_tokens_override: Some(MISSING_SEMICOLON_EXPECTED_TOKENS), + help: Some("statements must end with ';'"), + primary_label: Some("expected ';' to terminate statement"), + notes: &[], + }, + UNCLASSIFIED_SPEC, +]; + +#[derive(Clone, Copy)] +struct InterpretationHeuristic { + interpretation: ParseErrorInterpretation, + matches: fn(&ParseAttemptData) -> bool, +} + +const INTERPRETATION_HEURISTICS: &[InterpretationHeuristic] = + &[InterpretationHeuristic { interpretation: ParseErrorInterpretation::MissingSemicolon, matches: expects_semicolon }]; + +#[derive(Default)] +struct ParseAttemptData { + expected_tokens: Vec, + rules: Vec, +} + +impl ParseAttemptData { + fn from_error(err: &pest::error::Error) -> Self { + let Some(attempts) = err.parse_attempts() else { + return Self::default(); + }; + + let expected_tokens = attempts.expected_tokens().into_iter().map(|token| token.to_string()).collect::>(); + + let mut rules = Vec::new(); + for stack in attempts.call_stacks() { + if let Some(rule) = stack.deepest.get_rule() { + rules.push(*rule); + } + if let Some(rule) = stack.parent { + rules.push(rule); + } + } + + Self { expected_tokens, rules } + } + + fn expects_token(&self, token: &str) -> bool { + self.expected_tokens.iter().any(|candidate| candidate == token) + } + + // remove once used by one of the heuristic matcher + #[allow(dead_code)] + fn includes_rule(&self, rule: Rule) -> bool { + self.rules.contains(&rule) + } +} + +pub(crate) fn interpret_parse_error(input: &str, err: &pest::error::Error) -> ParseDiagnostic { + let failure_pos = error_start_offset(err); + let attempt_data = ParseAttemptData::from_error(err); + let interpretation = classify_interpretation(&attempt_data); + let spec = interpretation_spec(interpretation); + let span = spec.span_strategy.resolve(input, failure_pos); + let primary_message = match interpretation { + ParseErrorInterpretation::Unclassified => err.variant.message().into_owned(), + _ => "parsing error occurred.".to_owned(), + }; + + let mut diagnostic = ParseDiagnostic::new(interpretation, span, input, primary_message) + .with_expected_tokens(normalize_expected_tokens(&attempt_data.expected_tokens, spec)) + .with_labels(primary_labels(spec, span)) + .with_notes(spec.notes.iter().map(|note| (*note).to_owned()).collect()); + if let Some(help) = spec.help { + diagnostic = diagnostic.with_help(help); + } + diagnostic +} + +fn classify_interpretation(attempt_data: &ParseAttemptData) -> ParseErrorInterpretation { + INTERPRETATION_HEURISTICS + .iter() + .find(|heuristic| (heuristic.matches)(attempt_data)) + .map(|heuristic| heuristic.interpretation) + .unwrap_or(ParseErrorInterpretation::Unclassified) +} + +fn expects_semicolon(attempt_data: &ParseAttemptData) -> bool { + attempt_data.expects_token(";") +} + +fn interpretation_spec(interpretation: ParseErrorInterpretation) -> &'static InterpretationSpec { + INTERPRETATION_SPECS.iter().find(|spec| spec.interpretation == interpretation).unwrap_or(&UNCLASSIFIED_SPEC) +} + +fn normalize_expected_tokens(expected_tokens: &[String], spec: &InterpretationSpec) -> Vec { + if let Some(tokens) = spec.expected_tokens_override { + return tokens.iter().map(|token| (*token).to_owned()).collect(); + } + + expected_tokens.iter().map(|token| normalize_token(token)).collect::>().into_iter().collect() +} + +fn primary_labels(spec: &InterpretationSpec, span: ErrorSpan) -> Vec { + spec.primary_label.map(|label| vec![ParseDiagnosticLabel::new(span, label)]).unwrap_or_default() +} + +fn normalize_token(token: &str) -> String { + if token.chars().all(char::is_whitespace) { "WHITESPACE".to_string() } else { token.to_string() } +} + +fn error_start_offset(err: &pest::error::Error) -> usize { + match err.location { + pest::error::InputLocation::Pos(pos) => pos, + pest::error::InputLocation::Span((start, _)) => start, + } +} + +fn focused_error_start(input: &str, failure_pos: usize) -> usize { + if is_closing_delimiter_at(input, failure_pos) { + failure_pos + } else { + previous_non_whitespace_offset(input, failure_pos).unwrap_or(failure_pos) + } +} + +fn previous_non_whitespace_offset(input: &str, pos: usize) -> Option { + let prefix = input.get(..pos)?; + prefix.char_indices().rev().find_map(|(idx, ch)| if ch.is_whitespace() { None } else { Some(idx) }) +} + +fn is_closing_delimiter_at(input: &str, pos: usize) -> bool { + matches!(input.as_bytes().get(pos), Some(b')' | b']' | b'}')) +} diff --git a/silverscript-lang/src/errors.rs b/silverscript-lang/src/errors.rs new file mode 100644 index 00000000..caab450f --- /dev/null +++ b/silverscript-lang/src/errors.rs @@ -0,0 +1,52 @@ +use kaspa_txscript::script_builder::ScriptBuilderError; +use thiserror::Error; + +pub use crate::diagnostic::{ErrorSpan, ParseDiagnostic, ParseDiagnosticLabel, ParseDisplayLocation, ParseErrorInterpretation}; +use crate::span; + +#[derive(Debug, Error)] +pub enum CompilerError { + #[error("parse error: {0}")] + Parse(#[from] ParseDiagnostic), + #[error("unsupported feature: {0}")] + Unsupported(String), + #[error("invalid literal: {0}")] + InvalidLiteral(String), + #[error("undefined identifier: {0}")] + UndefinedIdentifier(String), + #[error("cyclic identifier reference: {0}")] + CyclicIdentifier(String), + #[error("script build error: {0}")] + ScriptBuild(#[from] ScriptBuilderError), + // QUESTION: not entierly sure about this pattern + #[error("{source}")] + Context { + #[source] + source: Box, + span: ErrorSpan, + }, +} + +impl CompilerError { + pub fn root(&self) -> &CompilerError { + let mut current = self; + while let Self::Context { source, .. } = current { + current = source; + } + current + } + + pub fn span(&self) -> Option { + match self { + Self::Context { span, .. } => Some(*span), + _ => None, + } + } + + pub fn with_span(self, span: &span::Span<'_>) -> Self { + if self.span().is_some() || matches!(self.root(), Self::Parse(_)) { + return self; + } + Self::Context { source: Box::new(self), span: ErrorSpan { start: span.start(), end: span.end() } } + } +} diff --git a/silverscript-lang/src/lib.rs b/silverscript-lang/src/lib.rs index 3ace8479..cdd68dfb 100644 --- a/silverscript-lang/src/lib.rs +++ b/silverscript-lang/src/lib.rs @@ -1,4 +1,7 @@ pub mod ast; pub mod compiler; pub mod debug; +pub mod diagnostic; +pub mod errors; pub mod parser; +pub mod span; diff --git a/silverscript-lang/src/parser.rs b/silverscript-lang/src/parser.rs index 0ba10fa9..e00bd2ec 100644 --- a/silverscript-lang/src/parser.rs +++ b/silverscript-lang/src/parser.rs @@ -1,16 +1,24 @@ use pest::Parser; -use pest::error::Error; use pest::iterators::Pairs; use pest_derive::Parser; +use crate::errors::ParseDiagnostic; + #[derive(Parser)] #[grammar = "silverscript.pest"] pub struct SilverScriptParser; -pub fn parse_source_file(input: &str) -> Result, Error> { - SilverScriptParser::parse(Rule::source_file, input) +pub fn parse_source_file(input: &str) -> Result, ParseDiagnostic> { + pest::set_error_detail(true); + SilverScriptParser::parse(Rule::source_file, input).map_err(|err| crate::diagnostic::interpret_parse_error(input, &err)) +} + +pub fn parse_expression(input: &str) -> Result, ParseDiagnostic> { + pest::set_error_detail(true); + SilverScriptParser::parse(Rule::expression, input).map_err(|err| crate::diagnostic::interpret_parse_error(input, &err)) } -pub fn parse_expression(input: &str) -> Result, Error> { - SilverScriptParser::parse(Rule::expression, input) +pub fn parse_type_name(input: &str) -> Result, ParseDiagnostic> { + pest::set_error_detail(true); + SilverScriptParser::parse(Rule::type_name, input).map_err(|err| crate::diagnostic::interpret_parse_error(input, &err)) } diff --git a/silverscript-lang/src/span.rs b/silverscript-lang/src/span.rs new file mode 100644 index 00000000..00e415d9 --- /dev/null +++ b/silverscript-lang/src/span.rs @@ -0,0 +1,81 @@ +use std::fmt; +use std::ops::Deref; + +use pest::Span as PestSpan; +use serde::Serialize; +use serde::Serializer; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Span<'i>(PestSpan<'i>); + +impl<'i> Span<'i> { + pub fn new(input: &'i str, start: usize, end: usize) -> Option { + PestSpan::new(input, start, end).map(Span) + } + + pub fn join(&self, other: &Span<'i>) -> Span<'i> { + let input = self.get_input(); + let start = self.start().min(other.start()); + let end = self.end().max(other.end()); + Span::new(input, start, end).unwrap_or(*self) + } +} + +impl<'i> Default for Span<'i> { + fn default() -> Self { + Span(PestSpan::new("", 0, 0).expect("synthetic span")) + } +} + +impl<'i> From> for Span<'i> { + fn from(span: PestSpan<'i>) -> Self { + Span(span) + } +} + +impl<'i> Deref for Span<'i> { + type Target = PestSpan<'i>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'i> fmt::Display for Span<'i> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let source = self.as_str(); + if source.is_empty() { f.write_str("") } else { f.write_str(source) } + } +} + +// serde serialize becomes display +impl<'i> Serialize for Span<'i> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +pub trait SpanUtils { + fn len(&self) -> usize; + fn is_empty(&self) -> bool { + self.len() == 0 + } + fn contains(&self, offset: usize) -> bool; +} + +impl<'i> SpanUtils for Span<'i> { + fn len(&self) -> usize { + self.end().saturating_sub(self.start()) + } + + fn contains(&self, offset: usize) -> bool { + offset >= self.start() && offset < self.end() + } +} + +pub fn join<'i>(left: &Span<'i>, right: &Span<'i>) -> Span<'i> { + left.join(right) +} diff --git a/silverscript-lang/tests/ast_json/require_test.ast.json b/silverscript-lang/tests/ast_json/require_test.ast.json index fd35aa8b..0ead523d 100644 --- a/silverscript-lang/tests/ast_json/require_test.ast.json +++ b/silverscript-lang/tests/ast_json/require_test.ast.json @@ -1,7 +1,7 @@ { "name": "Test", "params": [], - "constants": {}, + "constants": [], "functions": [ { "name": "main", diff --git a/silverscript-lang/tests/ast_json/yield_test.ast.json b/silverscript-lang/tests/ast_json/yield_test.ast.json index 156c0cba..b93d70f0 100644 --- a/silverscript-lang/tests/ast_json/yield_test.ast.json +++ b/silverscript-lang/tests/ast_json/yield_test.ast.json @@ -1,7 +1,7 @@ { "name": "YieldTest", "params": [], - "constants": {}, + "constants": [], "functions": [ { "name": "main", diff --git a/silverscript-lang/tests/ast_json_tests.rs b/silverscript-lang/tests/ast_json_tests.rs index 115224c4..7d4dea28 100644 --- a/silverscript-lang/tests/ast_json_tests.rs +++ b/silverscript-lang/tests/ast_json_tests.rs @@ -3,7 +3,7 @@ use std::fs; use silverscript_lang::ast::ContractAst; use silverscript_lang::compiler::{CompileOptions, compile_contract, compile_contract_ast}; -fn load_ast(name: &str) -> ContractAst { +fn load_ast(name: &str) -> ContractAst<'_> { let path = format!("{}/tests/ast_json/{name}", env!("CARGO_MANIFEST_DIR")); let json = fs::read_to_string(&path).unwrap_or_else(|err| panic!("failed to read {path}: {err}")); serde_json::from_str(&json).unwrap_or_else(|err| panic!("failed to parse {path}: {err}")) diff --git a/silverscript-lang/tests/ast_spans_tests.rs b/silverscript-lang/tests/ast_spans_tests.rs new file mode 100644 index 00000000..0dca9faf --- /dev/null +++ b/silverscript-lang/tests/ast_spans_tests.rs @@ -0,0 +1,60 @@ +use silverscript_lang::ast::{ExprKind, Statement, parse_contract_ast}; + +fn assert_span_text(source: &str, actual: &str, expected: &str) { + let start = source.find(expected).expect("expected text must exist in source"); + let end = start + expected.len(); + assert_eq!(actual, expected); + assert_eq!(&source[start..end], expected); +} + +#[test] +fn populates_contract_function_and_statement_spans() { + let source = r#" + contract Foo(int a) { + function bar(int b):(int) { + int x = a + b; + return(x); + } + } + "#; + let contract = parse_contract_ast(source).expect("contract should parse"); + + assert_span_text(source, contract.name_span.as_str(), "Foo"); + assert_span_text(source, contract.functions[0].name_span.as_str(), "bar"); + assert_span_text(source, contract.functions[0].body_span.as_str(), "int x = a + b;\n return(x);"); + + let first_stmt = &contract.functions[0].body[0]; + let Statement::VariableDefinition { span, .. } = first_stmt else { + panic!("expected first statement to be a variable definition"); + }; + assert_span_text(source, span.as_str(), "int x = a + b;"); +} + +#[test] +fn populates_slice_expression_spans() { + let source = r#" + contract SliceTest() { + function main(byte[] data) { + byte[] part = data.slice(1, 3); + } + } + "#; + let contract = parse_contract_ast(source).expect("contract should parse"); + let stmt = &contract.functions[0].body[0]; + + let Statement::VariableDefinition { expr: Some(expr), .. } = stmt else { + panic!("expected a variable definition with expression"); + }; + let ExprKind::Slice { source: base, start, end, span } = &expr.kind else { + panic!("expected slice expression"); + }; + let ExprKind::Identifier(_) = &base.kind else { + panic!("slice source should be an identifier"); + }; + + assert_span_text(source, expr.span.as_str(), "data.slice(1, 3)"); + assert_span_text(source, span.as_str(), ".slice(1, 3)"); + assert_span_text(source, base.span.as_str(), "data"); + assert_span_text(source, start.span.as_str(), "1"); + assert_span_text(source, end.span.as_str(), "3"); +} diff --git a/silverscript-lang/tests/cashc_valid_examples_tests.rs b/silverscript-lang/tests/cashc_valid_examples_tests.rs index 43c43b2b..60e2b8b6 100644 --- a/silverscript-lang/tests/cashc_valid_examples_tests.rs +++ b/silverscript-lang/tests/cashc_valid_examples_tests.rs @@ -41,7 +41,7 @@ fn parse_contract_param_types(source: &str) -> Vec { result } -fn dummy_expr_for_type(type_name: &str) -> Expr { +fn dummy_expr_for_type(type_name: &str) -> Expr<'static> { if type_name == "int" { return 0i64.into(); } @@ -125,7 +125,7 @@ fn build_sigscript(args: &[ArgValue], selector: Option) -> Vec { builder.drain() } -fn selector_for_compiled(compiled: &CompiledContract, function_name: &str) -> Option { +fn selector_for_compiled(compiled: &CompiledContract<'_>, function_name: &str) -> Option { if compiled.without_selector { None } else { diff --git a/silverscript-lang/tests/compiler_tests.rs b/silverscript-lang/tests/compiler_tests.rs index 90ba77d3..2729bb80 100644 --- a/silverscript-lang/tests/compiler_tests.rs +++ b/silverscript-lang/tests/compiler_tests.rs @@ -126,15 +126,15 @@ fn accepts_constructor_args_with_matching_types() { } "#; let args = vec![ - Expr::Int(7), - Expr::Bool(true), - Expr::String("hello".to_string()), - vec![1u8; 10].into(), - Expr::Byte(2), // Single byte for type 'byte' - vec![3u8; 4].into(), - vec![4u8; 32].into(), - vec![5u8; 65].into(), - vec![6u8; 64].into(), + Expr::int(7), + Expr::bool(true), + Expr::string("hello".to_string()), + Expr::bytes(vec![1u8; 10]), + Expr::byte(2), + Expr::bytes(vec![3u8; 4]), + Expr::bytes(vec![4u8; 32]), + Expr::bytes(vec![5u8; 65]), + Expr::bytes(vec![6u8; 64]), ]; compile_contract(source, &args, CompileOptions::default()).expect("compile succeeds"); } @@ -148,7 +148,7 @@ fn rejects_constructor_args_with_wrong_scalar_types() { } } "#; - let args = vec![Expr::Bool(true), Expr::Int(1), vec![1u8].into()]; + let args = vec![Expr::bool(true), Expr::int(1), Expr::bytes(vec![1u8])]; assert!(compile_contract(source, &args, CompileOptions::default()).is_err()); } @@ -161,7 +161,13 @@ fn rejects_constructor_args_with_wrong_byte_lengths() { } } "#; - let args = vec![vec![1u8; 2].into(), vec![2u8; 3].into(), vec![3u8; 31].into(), vec![4u8; 63].into(), vec![5u8; 66].into()]; + let args = vec![ + Expr::bytes(vec![1u8; 2]), + Expr::bytes(vec![2u8; 3]), + Expr::bytes(vec![3u8; 31]), + Expr::bytes(vec![4u8; 63]), + Expr::bytes(vec![5u8; 66]), + ]; assert!(compile_contract(source, &args, CompileOptions::default()).is_err()); } @@ -194,7 +200,7 @@ fn accepts_constructor_args_with_any_bytes_length() { } } "#; - let args = vec![vec![9u8; 128].into()]; + let args = vec![Expr::bytes(vec![9u8; 128])]; compile_contract(source, &args, CompileOptions::default()).expect("compile succeeds"); } @@ -208,7 +214,7 @@ fn build_sig_script_builds_expected_script() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let args = vec![vec![1u8, 2, 3, 4].into(), Expr::Int(7)]; + let args = vec![Expr::bytes(vec![1u8, 2, 3, 4]), Expr::int(7)]; let sigscript = compiled.build_sig_script("spend", args).expect("sigscript builds"); let selector = selector_for(&compiled, "spend"); @@ -233,7 +239,7 @@ fn build_sig_script_rejects_unknown_function() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("missing", vec![Expr::Int(1)]); + let result = compiled.build_sig_script("missing", vec![Expr::int(1)]); assert!(result.is_err()); } @@ -247,7 +253,7 @@ fn build_sig_script_rejects_wrong_argument_count() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![Expr::Int(1)]); + let result = compiled.build_sig_script("spend", vec![Expr::int(1)]); assert!(result.is_err()); } @@ -261,7 +267,7 @@ fn build_sig_script_rejects_wrong_argument_type() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![vec![1u8; 3].into()]); + let result = compiled.build_sig_script("spend", vec![Expr::bytes(vec![1u8; 3])]); assert!(result.is_err()); } @@ -317,7 +323,7 @@ fn rejects_external_call_without_entrypoint() { "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("helper", vec![Expr::Int(1)]); + let result = compiled.build_sig_script("helper", vec![Expr::int(1)]); assert!(result.is_err()); } @@ -345,7 +351,7 @@ fn build_sig_script_rejects_mismatched_bytes_length() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![vec![1u8; 5].into()]); + let result = compiled.build_sig_script("spend", vec![Expr::bytes(vec![1u8; 5])]); assert!(result.is_err()); let source = r#" @@ -356,7 +362,7 @@ fn build_sig_script_rejects_mismatched_bytes_length() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![vec![1u8; 4].into()]); + let result = compiled.build_sig_script("spend", vec![Expr::bytes(vec![1u8; 4])]); assert!(result.is_err()); } @@ -1389,7 +1395,7 @@ fn build_covenant_opcode_tx(sigscript: Vec, covenant_id_a: Hash, covenant_id (tx, entries) } -fn selector_for(compiled: &CompiledContract, function_name: &str) -> Option { +fn selector_for(compiled: &CompiledContract<'_>, function_name: &str) -> Option { if compiled.without_selector { None } else { @@ -3146,7 +3152,7 @@ fn compiles_script_size_and_runs_sum_array() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_size = compiled.script.len() as i64; - let sigscript = compiled.build_sig_script("main", vec![Expr::Int(expected_size)]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::int(expected_size)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "script size contract failed: {}", result.unwrap_err()); @@ -3173,7 +3179,7 @@ fn compiles_script_size_data_prefix_small_script() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_prefix = data_prefix_for_size(compiled.script.len()); - let sigscript = compiled.build_sig_script("main", vec![expected_prefix.into()]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::bytes(expected_prefix)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "scriptSizeDataPrefix small failed: {}", result.unwrap_err()); @@ -3194,7 +3200,7 @@ fn compiles_script_size_data_prefix_medium_script() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_prefix = data_prefix_for_size(compiled.script.len()); - let sigscript = compiled.build_sig_script("main", vec![expected_prefix.into()]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::bytes(expected_prefix)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "scriptSizeDataPrefix medium failed: {}", result.unwrap_err()); @@ -3215,7 +3221,7 @@ fn compiles_script_size_data_prefix_large_script() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_prefix = data_prefix_for_size(compiled.script.len()); - let sigscript = compiled.build_sig_script("main", vec![expected_prefix.into()]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::bytes(expected_prefix)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "scriptSizeDataPrefix large failed: {}", result.unwrap_err()); @@ -3506,3 +3512,32 @@ fn accepts_byte_array_with_constant_size() { "#; compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds with byte[HASH_SIZE]"); } + +#[test] +fn blake2b_int_and_byte_cast_forms_compile_to_identical_script() { + let source_plain = r#" + contract Test() { + entrypoint function test() { + int x = 5; + require(blake2b(x).length == 32); + } + } + "#; + + let source_cast = r#" + contract Test() { + entrypoint function test() { + int x = 5; + require(blake2b(byte[](x)).length == 32); + } + } + "#; + + let compiled_plain = compile_contract(source_plain, &[], CompileOptions::default()).expect("plain form compiles"); + let compiled_cast = compile_contract(source_cast, &[], CompileOptions::default()).expect("byte-cast form compiles"); + + assert_eq!( + compiled_plain.script, compiled_cast.script, + "blake2b(x) and blake2b(byte[](x)) should currently compile to identical scripts" + ); +} diff --git a/silverscript-lang/tests/date_literal_tests.rs b/silverscript-lang/tests/date_literal_tests.rs index e0606afc..6b86d1db 100644 --- a/silverscript-lang/tests/date_literal_tests.rs +++ b/silverscript-lang/tests/date_literal_tests.rs @@ -1,13 +1,13 @@ use chrono::NaiveDateTime; -use silverscript_lang::ast::{Expr, StatementKind, parse_contract_ast}; +use silverscript_lang::ast::{Expr, ExprKind, Statement, parse_contract_ast}; -fn extract_first_expr(source: &str) -> Expr { +fn extract_first_expr<'i>(source: &'i str) -> Expr<'i> { let ast = parse_contract_ast(source).expect("parse succeeds"); let function = &ast.functions[0]; let statement = &function.body[0]; - match &statement.kind { - StatementKind::VariableDefinition { expr, .. } => expr.clone().expect("missing initializer"), - StatementKind::Require { expr, .. } => expr.clone(), + match statement { + Statement::VariableDefinition { expr, .. } => expr.clone().expect("missing initializer"), + Statement::Require { expr, .. } => expr.clone(), _ => panic!("unexpected statement"), } } @@ -23,8 +23,8 @@ fn parses_date_literal_basic_iso() { } "#; let expr = extract_first_expr(source); - let Expr::Int(parsed) = expr else { - panic!("expected int literal"); + let Expr { kind: ExprKind::DateLiteral(parsed), .. } = expr else { + panic!("expected date literal"); }; let expected = NaiveDateTime::parse_from_str("2021-02-17T01:30:00", "%Y-%m-%dT%H:%M:%S").unwrap().and_utc().timestamp(); assert_eq!(parsed, expected); diff --git a/silverscript-lang/tests/debug_session_tests.rs b/silverscript-lang/tests/debug_session_tests.rs index 594fd3e3..81aea52f 100644 --- a/silverscript-lang/tests/debug_session_tests.rs +++ b/silverscript-lang/tests/debug_session_tests.rs @@ -20,25 +20,25 @@ fn example_contract_path() -> PathBuf { // Convenience harness for the canonical example contract used by baseline session tests. fn with_session(mut f: F) -> Result<(), Box> where - F: FnMut(&mut DebugSession<'_>) -> Result<(), Box>, + F: FnMut(&mut DebugSession<'_, '_>) -> Result<(), Box>, { let contract_path = example_contract_path(); assert!(contract_path.exists(), "example contract not found: {}", contract_path.display()); let source = fs::read_to_string(&contract_path)?; - with_session_for_source(&source, vec![Expr::Int(3), Expr::Int(10)], "hello", vec![Expr::Int(5), Expr::Int(5)], &mut f) + with_session_for_source(&source, vec![Expr::int(3), Expr::int(10)], "hello", vec![Expr::int(5), Expr::int(5)], &mut f) } // Generic harness that compiles a contract and boots a debugger session for a selected function call. fn with_session_for_source( source: &str, - ctor_args: Vec, + ctor_args: Vec>, function_name: &str, - function_args: Vec, + function_args: Vec>, mut f: F, ) -> Result<(), Box> where - F: FnMut(&mut DebugSession<'_>) -> Result<(), Box>, + F: FnMut(&mut DebugSession<'_, '_>) -> Result<(), Box>, { let parsed_contract = parse_contract_ast(source)?; assert_eq!(parsed_contract.params.len(), ctor_args.len()); @@ -132,7 +132,7 @@ contract BP() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(1)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(1)], |session| { session.run_to_first_executed_statement()?; // Line 8 is inside a multiline `require(...)` span and should still be hit. assert!(session.add_breakpoint(8), "expected breakpoint line to be valid"); @@ -157,7 +157,7 @@ contract Shadow(int x) { } "#; - with_session_for_source(source, vec![Expr::Int(7)], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![Expr::int(7)], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; // Function param `x` should shadow constructor constant `x` in visible debugger variables. @@ -185,7 +185,7 @@ contract ShadowMath(int fee) { } "#; - with_session_for_source(source, vec![Expr::Int(2)], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![Expr::int(2)], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; session.step_over()?; @@ -216,7 +216,7 @@ contract FieldOffset(int c) { } "#; - with_session_for_source(source, vec![Expr::Int(2)], "main", vec![Expr::Int(5)], |session| { + with_session_for_source(source, vec![Expr::int(2)], "main", vec![Expr::int(5)], |session| { session.run_to_first_executed_statement()?; let a = session.variable_by_name("a")?; @@ -242,7 +242,7 @@ contract FieldMath(int c) { } "#; - with_session_for_source(source, vec![Expr::Int(2)], "main", vec![Expr::Int(5)], |session| { + with_session_for_source(source, vec![Expr::int(2)], "main", vec![Expr::int(5)], |session| { session.run_to_first_executed_statement()?; for _ in 0..4 { @@ -272,7 +272,7 @@ contract Virtuals() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; let first = session.current_location().ok_or("missing first location")?; assert!(matches!(first.kind, MappingKind::Virtual {})); @@ -302,7 +302,7 @@ contract OpcodeCursor() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; let start = session.current_span().ok_or("missing start span")?; assert_eq!(start.line, 5); @@ -330,7 +330,7 @@ contract VirtualBp() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; assert!(session.add_breakpoint(6), "line with virtual assignment should be a valid breakpoint"); let hit = session.continue_to_breakpoint()?; @@ -354,7 +354,7 @@ contract LocalVars() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; assert!(session.variable_by_name("x").is_err(), "x should not exist before its statement executes"); @@ -401,7 +401,7 @@ contract InlineCalls() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; let start = session.current_span().ok_or("missing start span")?; assert_eq!(start.line, 10); @@ -420,7 +420,7 @@ contract InlineCalls() { Ok(()) })?; - with_session_for_source(source, vec![], "main", vec![Expr::Int(3)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(3)], |session| { session.run_to_first_executed_statement()?; session.step_into()?; let mut in_callee = session.current_span().ok_or("missing span in callee")?; @@ -464,7 +464,7 @@ contract Repeat() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(0)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(0)], |session| { session.run_to_first_executed_statement()?; let start = session.current_span().ok_or("missing start span")?; assert_eq!(start.line, 10, "first source step should be caller line, not callee internals"); @@ -490,7 +490,7 @@ contract Repeat() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(0)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(0)], |session| { session.run_to_first_executed_statement()?; let mut lines = vec![session.current_span().ok_or("missing initial span")?.line]; @@ -572,7 +572,7 @@ contract DebugPoC(int const) { } "#; - with_session_for_source(source, vec![Expr::Int(0)], "main", vec![Expr::Int(0), Expr::Int(0)], |session| { + with_session_for_source(source, vec![Expr::int(0)], "main", vec![Expr::int(0), Expr::int(0)], |session| { session.run_to_first_executed_statement()?; let initial = session.current_location().ok_or("missing initial location")?; @@ -616,7 +616,7 @@ contract InlineParams() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(4)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(4)], |session| { session.run_to_first_executed_statement()?; let mut saw_inline_param = false; @@ -662,7 +662,7 @@ contract NestedArgs() { } "#; - with_session_for_source(source, vec![], "main", vec![Expr::Int(0)], |session| { + with_session_for_source(source, vec![], "main", vec![Expr::int(0)], |session| { session.run_to_first_executed_statement()?; let start = session.current_span().ok_or("missing start span")?; assert_eq!(start.line, 15); diff --git a/silverscript-lang/tests/parse_diagnostics_tests.rs b/silverscript-lang/tests/parse_diagnostics_tests.rs new file mode 100644 index 00000000..a0adf65a --- /dev/null +++ b/silverscript-lang/tests/parse_diagnostics_tests.rs @@ -0,0 +1,53 @@ +use silverscript_lang::ast::parse_contract_ast; +use silverscript_lang::errors::{CompilerError, ParseErrorInterpretation}; + +#[test] +fn full_diagnostic_from_missing_semicolon() { + let source = r#" + contract Foo() { + function bar(byte[] data) { + int x = a + b + int t = x + a; + } + } + "#; + let err = parse_contract_ast(source).expect_err("source without semicolon must fail parsing"); + let CompilerError::Parse(diagnostic) = err else { + panic!("expected parse error"); + }; + assert_eq!(diagnostic.interpretation(), ParseErrorInterpretation::MissingSemicolon); + assert_eq!(diagnostic.code(), "missing_semicolon"); + assert_eq!(diagnostic.expected_tokens(), ["WHITESPACE", "/*", "//", ";"]); + assert_eq!(diagnostic.primary_message(), "parsing error occurred."); + assert_eq!(diagnostic.help(), Some("statements must end with ';'")); + assert_eq!(diagnostic.labels().len(), 1); + + let span = diagnostic.span(); + assert_eq!(span.start, span.end); + assert_eq!(&source[span.start..span.start + 1], "b"); + + let location = diagnostic.display_location(); + assert!(location.line() > 0); + assert!(location.column() > 0); + assert!(location.line_text().contains("int x = a + b")); +} + +#[test] +fn unclassified_diagnostic_preserves_pest_message() { + let source = r#" + pragma silverscript ^0.1.0; + + contract Foo() { + ??? + } + "#; + + let err = parse_contract_ast(source).expect_err("invalid token must fail parsing"); + let CompilerError::Parse(diagnostic) = err else { + panic!("expected parse error"); + }; + + assert_eq!(diagnostic.interpretation(), ParseErrorInterpretation::Unclassified); + assert_ne!(diagnostic.primary_message(), "parsing error occurred."); + assert!(diagnostic.primary_message().contains("expected")); +} diff --git a/silverscript-lang/tests/parser_tests.rs b/silverscript-lang/tests/parser_tests.rs index 63cde999..f63ce1aa 100644 --- a/silverscript-lang/tests/parser_tests.rs +++ b/silverscript-lang/tests/parser_tests.rs @@ -50,3 +50,25 @@ fn parses_arrays_and_introspection() { panic!("{}", err); } } + +#[test] +fn parses_input_sigscript_and_rejects_output_sigscript() { + let input_ok = r#" + contract SigScriptCheck() { + function verify(int idx) { + require(tx.inputs[idx].sigScript.length >= 0); + } + } + "#; + assert!(parse_source_file(input_ok).is_ok()); + + let input_bad = r#" + contract SigScriptCheck() { + function verify(int idx) { + // outputs don't have a sigScript field, so parsing is expected to fail + require(tx.outputs[idx].sigScript.length >= 0); + } + } + "#; + assert!(parse_source_file(input_bad).is_err()); +} diff --git a/silverscript-lang/tests/silverc_tests.rs b/silverscript-lang/tests/silverc_tests.rs index 5f7ba4ef..dd0d2ff0 100644 --- a/silverscript-lang/tests/silverc_tests.rs +++ b/silverscript-lang/tests/silverc_tests.rs @@ -1,5 +1,5 @@ use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; use kaspa_consensus_core::hashing::sighash::SigHashReusedValuesUnsync; @@ -11,9 +11,38 @@ use kaspa_txscript::caches::Cache; use kaspa_txscript::script_builder::ScriptBuilder; use kaspa_txscript::{EngineCtx, EngineFlags, TxScriptEngine}; use rand::RngCore; -use silverscript_lang::ast::Expr; +use silverscript_lang::ast::{ContractAst, Expr}; use silverscript_lang::compiler::{CompiledContract, function_branch_index}; +const BASIC_CONTRACT_SOURCE: &str = r#" + contract Basic() { + entrypoint function main() { + require(true); + } + } + "#; + +const WITH_CTOR_SOURCE: &str = r#" + contract WithCtor(int a) { + entrypoint function main() { + require(a == 7); + } + } + "#; + +fn silverc() -> Command { + Command::new(env!("CARGO_BIN_EXE_silverc")) +} + +fn write_basic_contract(path: &Path) { + fs::write(path, BASIC_CONTRACT_SOURCE).expect("write source"); +} + +fn write_with_ctor_contract(path: &Path) { + fs::write(path, WITH_CTOR_SOURCE).expect("write source"); +} + +// TODO: move to tempfile crate or manually delete as a test tear down fn temp_dir(name: &str) -> PathBuf { let mut rng = rand::thread_rng(); let dir = std::env::temp_dir().join(format!("silverc_test_{name}_{}", rng.next_u64())); @@ -56,16 +85,9 @@ fn run_script_with_selector(script: Vec, selector: Option) -> Result<() fn silverc_defaults_output_path_and_empty_ctor_args() { let dir = temp_dir("default"); let src_path = dir.join("basic.sil"); - let source = r#" - contract Basic() { - entrypoint function main() { - require(true); - } - } - "#; - fs::write(&src_path, source).expect("write source"); + write_basic_contract(&src_path); - let status = Command::new(env!("CARGO_BIN_EXE_silverc")).arg(src_path.to_str().unwrap()).status().expect("run silverc"); + let status = silverc().arg(src_path.to_str().unwrap()).status().expect("run silverc"); assert!(status.success()); let out_path = dir.join("basic.json"); @@ -74,24 +96,34 @@ fn silverc_defaults_output_path_and_empty_ctor_args() { assert_eq!(compiled.contract_name, "Basic"); } +#[test] +fn silverc_stdout_flag_overrides_output_file() { + let dir = temp_dir("compile_stdout"); + let src_path = dir.join("basic.sil"); + let out_path = dir.join("compiled.json"); + write_basic_contract(&src_path); + + let output = + silverc().arg(src_path.to_str().unwrap()).arg("-o").arg(out_path.to_str().unwrap()).arg("-c").output().expect("run silverc"); + assert!(output.status.success()); + + let stdout = String::from_utf8(output.stdout).expect("decode stdout"); + let compiled: CompiledContract = serde_json::from_str(&stdout).expect("parse compiled json"); + assert_eq!(compiled.contract_name, "Basic"); + assert!(!out_path.exists()); +} + #[test] fn silverc_accepts_constructor_args_and_output_flag() { let dir = temp_dir("ctor"); let src_path = dir.join("with_ctor.sil"); let out_path = dir.join("out.json"); let ctor_path = dir.join("ctor.json"); - let source = r#" - contract WithCtor(int a) { - entrypoint function main() { - require(a == 7); - } - } - "#; - fs::write(&src_path, source).expect("write source"); - let ctor_args = vec![Expr::Int(7)]; + write_with_ctor_contract(&src_path); + let ctor_args = vec![Expr::int(7)]; fs::write(&ctor_path, serde_json::to_string(&ctor_args).expect("serialize ctor args")).expect("write ctor args"); - let status = Command::new(env!("CARGO_BIN_EXE_silverc")) + let status = silverc() .arg(src_path.to_str().unwrap()) .arg("--constructor-args") .arg(ctor_path.to_str().unwrap()) @@ -108,3 +140,40 @@ fn silverc_accepts_constructor_args_and_output_flag() { if compiled.without_selector { None } else { Some(function_branch_index(&compiled.ast, "main").expect("selector resolved")) }; assert!(run_script_with_selector(compiled.script, selector).is_ok()); } + +#[test] +fn silverc_ast_only_defaults_to_stdout() { + let dir = temp_dir("ast_stdout"); + let src_path = dir.join("basic.sil"); + write_basic_contract(&src_path); + + let output = silverc().arg(src_path.to_str().unwrap()).arg("--ast-only").output().expect("run silverc"); + assert!(output.status.success()); + + let stdout = String::from_utf8(output.stdout).expect("decode stdout"); + let ast: ContractAst<'static> = serde_json::from_str(&stdout).expect("parse ast json"); + assert_eq!(ast.name, "Basic"); + assert!(!dir.join("basic.json").exists()); +} + +#[test] +fn silverc_ast_only_writes_file_with_output_flag() { + let dir = temp_dir("ast_file"); + let src_path = dir.join("basic.sil"); + let out_path = dir.join("basic.ast.json"); + write_basic_contract(&src_path); + + let output = silverc() + .arg(src_path.to_str().unwrap()) + .arg("--ast-only") + .arg("-o") + .arg(out_path.to_str().unwrap()) + .output() + .expect("run silverc"); + assert!(output.status.success()); + assert!(output.stdout.is_empty()); + + let ast_json = fs::read_to_string(&out_path).expect("read ast output"); + let ast: ContractAst<'static> = serde_json::from_str(&ast_json).expect("parse ast json"); + assert_eq!(ast.name, "Basic"); +} diff --git a/silverscript-lang/tests/tutorial_rust_examples_tests.rs b/silverscript-lang/tests/tutorial_rust_examples_tests.rs index 146a14b1..2a8d2252 100644 --- a/silverscript-lang/tests/tutorial_rust_examples_tests.rs +++ b/silverscript-lang/tests/tutorial_rust_examples_tests.rs @@ -13,7 +13,7 @@ fn tutorial_rust_programmatic_compilation_example() { } "#; - let constructor_args = vec![Expr::Int(100)]; + let constructor_args = vec![Expr::int(100)]; let compiled = compile_contract(source, &constructor_args, CompileOptions::default()) .expect("programmatic compilation example should compile"); From 4ecc23c4dbe57238a5c549d81110e1fc3c320c97 Mon Sep 17 00:00:00 2001 From: Manyfestation <240733973+Manyfestation@users.noreply.github.com> Date: Wed, 25 Feb 2026 21:44:33 +0200 Subject: [PATCH 2/5] fmt --- silverscript-lang/src/compiler.rs | 15 ++++------- .../src/compiler/debug_recording.rs | 8 +----- silverscript-lang/src/debug.rs | 2 +- silverscript-lang/src/debug/session.rs | 26 +++++++------------ 4 files changed, 17 insertions(+), 34 deletions(-) diff --git a/silverscript-lang/src/compiler.rs b/silverscript-lang/src/compiler.rs index 9b47b384..284df8c8 100644 --- a/silverscript-lang/src/compiler.rs +++ b/silverscript-lang/src/compiler.rs @@ -9,9 +9,9 @@ use crate::ast::{ StateBindingAst, StateFieldExpr, Statement, TimeVar, TypeBase, TypeRef, UnaryOp, UnarySuffixKind, parse_contract_ast, parse_type_ref, }; -pub use crate::errors::{CompilerError, ErrorSpan}; use crate::debug::labels::synthetic; use crate::debug::{DebugInfo, SourceSpan}; +pub use crate::errors::{CompilerError, ErrorSpan}; use crate::span; mod debug_recording; @@ -2369,10 +2369,9 @@ fn expand_inline_arg_placeholders<'i>( visiting.remove(&name); Ok(expanded) } - ExprKind::Unary { op, expr } => Ok(Expr::new( - ExprKind::Unary { op, expr: Box::new(expand_inline_arg_placeholders(*expr, env, visiting)?) }, - span, - )), + ExprKind::Unary { op, expr } => { + Ok(Expr::new(ExprKind::Unary { op, expr: Box::new(expand_inline_arg_placeholders(*expr, env, visiting)?) }, span)) + } ExprKind::Binary { op, left, right } => Ok(Expr::new( ExprKind::Binary { op, @@ -2439,11 +2438,7 @@ fn expand_inline_arg_placeholders<'i>( span, )), ExprKind::Introspection { kind, index, field_span } => Ok(Expr::new( - ExprKind::Introspection { - kind, - index: Box::new(expand_inline_arg_placeholders(*index, env, visiting)?), - field_span, - }, + ExprKind::Introspection { kind, index: Box::new(expand_inline_arg_placeholders(*index, env, visiting)?), field_span }, span, )), ExprKind::UnarySuffix { source, kind, span: suffix_span } => Ok(Expr::new( diff --git a/silverscript-lang/src/compiler/debug_recording.rs b/silverscript-lang/src/compiler/debug_recording.rs index ff84dd62..bf8f23cd 100644 --- a/silverscript-lang/src/compiler/debug_recording.rs +++ b/silverscript-lang/src/compiler/debug_recording.rs @@ -379,13 +379,7 @@ impl<'i> DebugSink<'i> { }); } - pub fn record_compiled_function( - &mut self, - name: &str, - script_len: usize, - debug: &FunctionDebugRecorder<'i>, - offset: usize, - ) { + pub fn record_compiled_function(&mut self, name: &str, script_len: usize, debug: &FunctionDebugRecorder<'i>, offset: usize) { let Some(rec) = self.recorder_mut() else { return; }; diff --git a/silverscript-lang/src/debug.rs b/silverscript-lang/src/debug.rs index 020ed760..1514ed93 100644 --- a/silverscript-lang/src/debug.rs +++ b/silverscript-lang/src/debug.rs @@ -1,6 +1,6 @@ use crate::ast::Expr; -use serde::{Deserialize, Serialize}; use crate::span; +use serde::{Deserialize, Serialize}; pub mod presentation; pub mod session; diff --git a/silverscript-lang/src/debug/session.rs b/silverscript-lang/src/debug/session.rs index 780613b1..8c3dd4bf 100644 --- a/silverscript-lang/src/debug/session.rs +++ b/silverscript-lang/src/debug/session.rs @@ -673,11 +673,7 @@ impl<'a, 'i> DebugSession<'a, 'i> { stacks.dstack.iter().map(|item| encode_hex(item)).collect() } - fn evaluate_update_with_shadow_vm( - &self, - function_name: &str, - update: &DebugVariableUpdate<'i>, - ) -> Result { + fn evaluate_update_with_shadow_vm(&self, function_name: &str, update: &DebugVariableUpdate<'i>) -> Result { self.evaluate_expr_with_shadow_vm(function_name, &update.type_name, &update.expr) } @@ -687,12 +683,7 @@ impl<'a, 'i> DebugSession<'a, 'i> { /// that pushes current param values then executes the bytecode, run on fresh VM, /// read result from top of stack. This guarantees debugger sees same semantics as /// real execution without duplicating evaluation logic. - fn evaluate_expr_with_shadow_vm( - &self, - function_name: &str, - type_name: &str, - expr: &Expr<'i>, - ) -> Result { + fn evaluate_expr_with_shadow_vm(&self, function_name: &str, type_name: &str, expr: &Expr<'i>) -> Result { let params = self.shadow_param_values(function_name)?; let mut param_indexes = HashMap::new(); let mut param_types = HashMap::new(); @@ -909,11 +900,14 @@ mod tests { .evaluate_expr_with_shadow_vm( "f", "int", - &Expr::new(ExprKind::Binary { - op: BinaryOp::Add, - left: Box::new(Expr::identifier("a")), - right: Box::new(Expr::identifier("b")), - }, span::Span::default()), + &Expr::new( + ExprKind::Binary { + op: BinaryOp::Add, + left: Box::new(Expr::identifier("a")), + right: Box::new(Expr::identifier("b")), + }, + span::Span::default(), + ), ) .unwrap(); assert!(matches!(value, DebugValue::Int(12))); From 49c7e354c456e29146bf937a0ac3081c15492874 Mon Sep 17 00:00:00 2001 From: Manyfestation <240733973+Manyfestation@users.noreply.github.com> Date: Wed, 25 Feb 2026 23:21:41 +0200 Subject: [PATCH 3/5] debugger: fix tx-context local eval and loop index visibility --- silverscript-lang/src/compiler.rs | 12 +- .../src/compiler/debug_recording.rs | 29 +++++ silverscript-lang/src/debug/session.rs | 34 +++++- .../tests/debug_session_tests.rs | 112 +++++++++++++++++- 4 files changed, 182 insertions(+), 5 deletions(-) diff --git a/silverscript-lang/src/compiler.rs b/silverscript-lang/src/compiler.rs index 284df8c8..72e52bca 100644 --- a/silverscript-lang/src/compiler.rs +++ b/silverscript-lang/src/compiler.rs @@ -1286,11 +1286,12 @@ fn compile_statement<'i>( script_size, debug_recorder, ), - Statement::For { ident, start, end, body, .. } => compile_for_statement( + Statement::For { ident, start, end, body, span, .. } => compile_for_statement( ident, start, end, body, + *span, env, params, types, @@ -2112,6 +2113,7 @@ fn compile_for_statement<'i>( start_expr: &Expr<'i>, end_expr: &Expr<'i>, body: &[Statement<'i>], + for_span: span::Span<'i>, env: &mut HashMap>, params: &HashMap, types: &mut HashMap, @@ -2134,9 +2136,17 @@ fn compile_for_statement<'i>( } let name = ident.to_string(); + let loop_span = SourceSpan::from(for_span); let previous = env.get(&name).cloned(); for value in start..end { env.insert(name.clone(), Expr::int(value)); + debug_recorder.record_virtual_binding( + name.clone(), + "int".to_string(), + Expr::int(value), + builder.script().len(), + Some(loop_span), + ); compile_block( body, env, diff --git a/silverscript-lang/src/compiler/debug_recording.rs b/silverscript-lang/src/compiler/debug_recording.rs index bf8f23cd..e6ba2c6f 100644 --- a/silverscript-lang/src/compiler/debug_recording.rs +++ b/silverscript-lang/src/compiler/debug_recording.rs @@ -196,6 +196,35 @@ impl<'i> FunctionDebugRecorder<'i> { Ok(()) } + /// Emits a virtual debug step that binds a synthetic local variable. + /// Used by lowered constructs (for example unrolled loops) to keep + /// source-level locals visible even when no dedicated statement exists. + pub fn record_virtual_binding( + &mut self, + name: String, + type_name: String, + expr: Expr<'i>, + bytecode_offset: usize, + span: Option, + ) { + if !self.enabled { + return; + } + let Some(sequence) = self.push_event(bytecode_offset, bytecode_offset, span, DebugEventKind::Virtual {}) else { + return; + }; + self.variable_updates.push(DebugVariableUpdate { + name, + type_name, + expr, + bytecode_offset, + span, + function: self.function_name.clone(), + sequence, + frame_id: self.frame_id, + }); + } + /// Starts an inline call recording session and returns a child recorder for /// callee body statements. pub fn start_inline_call_recording(&mut self, span: Option, bytecode_offset: usize, callee: &str) -> Self { diff --git a/silverscript-lang/src/debug/session.rs b/silverscript-lang/src/debug/session.rs index 8c3dd4bf..63ebce19 100644 --- a/silverscript-lang/src/debug/session.rs +++ b/silverscript-lang/src/debug/session.rs @@ -1,8 +1,9 @@ use std::collections::{HashMap, HashSet}; use kaspa_consensus_core::hashing::sighash::SigHashReusedValuesUnsync; -use kaspa_consensus_core::tx::PopulatedTransaction; +use kaspa_consensus_core::tx::{PopulatedTransaction, TransactionInput, UtxoEntry}; use kaspa_txscript::caches::Cache; +use kaspa_txscript::covenants::CovenantsContext; use kaspa_txscript::script_builder::ScriptBuilder; use kaspa_txscript::{DynOpcodeImplementation, EngineCtx, EngineFlags, TxScriptEngine, parse_script}; use serde::{Deserialize, Serialize}; @@ -19,6 +20,15 @@ pub type DebugReused = SigHashReusedValuesUnsync; pub type DebugOpcode<'a> = DynOpcodeImplementation, DebugReused>; pub type DebugEngine<'a> = TxScriptEngine<'a, DebugTx<'a>, DebugReused>; +#[derive(Clone, Copy)] +pub struct ShadowTxContext<'a> { + pub tx: &'a DebugTx<'a>, + pub input: &'a TransactionInput, + pub input_index: usize, + pub utxo_entry: &'a UtxoEntry, + pub covenants_ctx: &'a CovenantsContext, +} + #[derive(Debug, Clone)] pub enum DebugValue { Int(i64), @@ -80,6 +90,7 @@ pub struct OpcodeMeta { pub struct DebugSession<'a, 'i> { engine: DebugEngine<'a>, + shadow_tx_context: Option>, opcodes: Vec>>, op_displays: Vec, opcode_offsets: Vec, @@ -178,6 +189,7 @@ impl<'a, 'i> DebugSession<'a, 'i> { Ok(Self { engine, + shadow_tx_context: None, opcodes, op_displays, opcode_offsets, @@ -205,6 +217,11 @@ impl<'a, 'i> DebugSession<'a, 'i> { Ok(Some(self.state())) } + pub fn with_shadow_tx_context(mut self, shadow_tx_context: ShadowTxContext<'a>) -> Self { + self.shadow_tx_context = Some(shadow_tx_context); + self + } + /// Step into: advance to next source step regardless of call depth. pub fn step_into(&mut self) -> Result, kaspa_txscript_errors::TxScriptError> { self.step_with_depth_predicate(|_, _| true) @@ -725,8 +742,19 @@ impl<'a, 'i> DebugSession<'a, 'i> { fn execute_shadow_script(&self, script: &[u8]) -> Result, String> { let sig_cache = Cache::new(0); let reused_values = SigHashReusedValuesUnsync::new(); - let mut engine: DebugEngine<'_> = - TxScriptEngine::new(EngineCtx::new(&sig_cache).with_reused(&reused_values), EngineFlags { covenants_enabled: true }); + let mut engine: DebugEngine<'_> = if let Some(shadow) = self.shadow_tx_context { + let ctx = EngineCtx::new(&sig_cache).with_reused(&reused_values).with_covenants_ctx(shadow.covenants_ctx); + TxScriptEngine::from_transaction_input( + shadow.tx, + shadow.input, + shadow.input_index, + shadow.utxo_entry, + ctx, + EngineFlags { covenants_enabled: true }, + ) + } else { + TxScriptEngine::new(EngineCtx::new(&sig_cache).with_reused(&reused_values), EngineFlags { covenants_enabled: true }) + }; for opcode in parse_script::, DebugReused>(script) { let opcode = opcode.map_err(|err| format!("failed to parse shadow script: {err}"))?; engine.execute_opcode(opcode).map_err(|err| format!("failed to execute shadow script: {err}"))?; diff --git a/silverscript-lang/tests/debug_session_tests.rs b/silverscript-lang/tests/debug_session_tests.rs index 81aea52f..ae15adc2 100644 --- a/silverscript-lang/tests/debug_session_tests.rs +++ b/silverscript-lang/tests/debug_session_tests.rs @@ -3,14 +3,21 @@ use std::error::Error; use std::fs; use std::path::PathBuf; +use kaspa_consensus_core::Hash; use kaspa_consensus_core::hashing::sighash::SigHashReusedValuesUnsync; +use kaspa_consensus_core::tx::{ + PopulatedTransaction, ScriptPublicKey, Transaction, TransactionId, TransactionInput, TransactionOutpoint, TransactionOutput, + UtxoEntry, VerifiableTransaction, +}; use kaspa_txscript::caches::Cache; +use kaspa_txscript::covenants::CovenantsContext; +use kaspa_txscript::opcodes::codes::OpTrue; use kaspa_txscript::{EngineCtx, EngineFlags}; use silverscript_lang::ast::{Expr, parse_contract_ast}; use silverscript_lang::compiler::{CompileOptions, compile_contract}; use silverscript_lang::debug::MappingKind; -use silverscript_lang::debug::session::DebugSession; +use silverscript_lang::debug::session::{DebugSession, ShadowTxContext}; fn example_contract_path() -> PathBuf { let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -677,3 +684,106 @@ contract NestedArgs() { Ok(()) }) } + +#[test] +fn debug_session_exposes_loop_index_variable_i() -> Result<(), Box> { + let source = r#"pragma silverscript ^0.1.0; + +contract LoopIndex() { + entrypoint function main() { + int sum = 0; + for(i,0,2){ + if(i < 2){ + sum = sum + i; + } + } + require(sum >= 0); + } +} +"#; + + with_session_for_source(source, vec![], "main", vec![], |session| { + session.run_to_first_executed_statement()?; + let mut saw_loop_index = false; + + for _ in 0..12 { + if let Ok(i) = session.variable_by_name("i") { + assert_eq!(session.format_value(&i.type_name, &i.value), "0"); + saw_loop_index = true; + break; + } + if session.step_over()?.is_none() { + break; + } + } + + assert!(saw_loop_index, "expected loop index 'i' to be visible while stepping loop body"); + Ok(()) + }) +} + +#[test] +fn debug_session_shadow_eval_uses_tx_context_for_covenant_opcode_locals() -> Result<(), Box> { + let source = r#"pragma silverscript ^0.1.0; + +contract CovLocal() { + entrypoint function main() { + byte[32] covid = OpInputCovenantId(this.activeInputIndex); + require(covid == covid); + } +} +"#; + + let compile_opts = CompileOptions { record_debug_infos: true, ..Default::default() }; + let compiled = compile_contract(source, &[], compile_opts)?; + let debug_info = compiled.debug_info.clone(); + let sigscript = compiled.build_sig_script("main", vec![])?; + + let input = TransactionInput { + previous_outpoint: TransactionOutpoint { transaction_id: TransactionId::from_bytes([0x44u8; 32]), index: 0 }, + signature_script: sigscript.clone(), + sequence: 0, + sig_op_count: 0, + }; + let output = TransactionOutput { value: 1000, script_public_key: ScriptPublicKey::new(0, vec![OpTrue].into()), covenant: None }; + let tx = Transaction::new(1, vec![input], vec![output], 0, Default::default(), 0, vec![]); + + let covenant_id = Hash::from_bytes([0x11u8; 32]); + let utxo_entry = + UtxoEntry::new(1000, ScriptPublicKey::new(0, compiled.script.clone().into()), 0, tx.is_coinbase(), Some(covenant_id)); + let populated_tx = PopulatedTransaction::new(&tx, vec![utxo_entry]); + let cov_ctx = CovenantsContext::from_tx(&populated_tx)?; + + let sig_cache = Cache::new(10_000); + let reused_values = SigHashReusedValuesUnsync::new(); + let ctx = EngineCtx::new(&sig_cache).with_reused(&reused_values).with_covenants_ctx(&cov_ctx); + let input_ref = &tx.inputs[0]; + let utxo_ref = populated_tx.utxo(0).ok_or("missing utxo for input 0")?; + let engine = silverscript_lang::debug::session::DebugEngine::from_transaction_input( + &populated_tx, + input_ref, + 0, + utxo_ref, + ctx, + EngineFlags { covenants_enabled: true }, + ); + + let shadow_ctx = + ShadowTxContext { tx: &populated_tx, input: input_ref, input_index: 0, utxo_entry: utxo_ref, covenants_ctx: &cov_ctx }; + + let mut session = DebugSession::full(&sigscript, &compiled.script, source, debug_info, engine)?.with_shadow_tx_context(shadow_ctx); + session.run_to_first_executed_statement()?; + + for _ in 0..4 { + if let Ok(covid) = session.variable_by_name("covid") { + let rendered = session.format_value(&covid.type_name, &covid.value); + assert_eq!(rendered, format!("0x{}", "11".repeat(32))); + return Ok(()); + } + if session.step_over()?.is_none() { + break; + } + } + + Err("expected covid local to be evaluated using tx context".into()) +} From 9031d3edb6528ad3e03441e9ec26e7eaad5eb464 Mon Sep 17 00:00:00 2001 From: Manyfestation <240733973+Manyfestation@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:25:20 +0200 Subject: [PATCH 4/5] refactor: split debugger into separate crates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename debug.rs → debug_info.rs in silverscript-lang (types-only module) - Create debugger-session library crate (session runtime, presentation) - Create cli-debugger binary crate (renamed from sil-debug) - Migrate debug session tests and CLI smoke test to new crates - Update all imports across workspace --- Cargo.lock | 28 +++++++++++++++++++ Cargo.toml | 7 ++++- debugger/cli/Cargo.toml | 22 +++++++++++++++ .../sil-debug.rs => debugger/cli/src/main.rs | 4 +-- .../cli/tests/cli_tests.rs | 12 ++++---- debugger/cli/tests/if_statement.sil | 17 +++++++++++ debugger/session/Cargo.toml | 24 ++++++++++++++++ debugger/session/src/lib.rs | 2 ++ .../session/src}/presentation.rs | 5 ++-- .../debug => debugger/session/src}/session.rs | 18 ++++++------ .../session}/tests/debug_session_tests.rs | 8 +++--- .../session/tests/examples/debug_messages.sil | 8 ++++++ .../session/tests/examples/if_statement.sil | 17 +++++++++++ silverscript-lang/src/compiler.rs | 4 +-- .../src/compiler/debug_recording.rs | 2 +- .../src/{debug.rs => debug_info.rs} | 3 -- silverscript-lang/src/lib.rs | 2 +- 17 files changed, 153 insertions(+), 30 deletions(-) create mode 100644 debugger/cli/Cargo.toml rename silverscript-lang/src/bin/sil-debug.rs => debugger/cli/src/main.rs (99%) rename silverscript-lang/tests/debugger_cli_tests.rs => debugger/cli/tests/cli_tests.rs (80%) create mode 100644 debugger/cli/tests/if_statement.sil create mode 100644 debugger/session/Cargo.toml create mode 100644 debugger/session/src/lib.rs rename {silverscript-lang/src/debug => debugger/session/src}/presentation.rs (98%) rename {silverscript-lang/src/debug => debugger/session/src}/session.rs (98%) rename {silverscript-lang => debugger/session}/tests/debug_session_tests.rs (98%) create mode 100644 debugger/session/tests/examples/debug_messages.sil create mode 100644 debugger/session/tests/examples/if_statement.sil rename silverscript-lang/src/{debug.rs => debug_info.rs} (99%) diff --git a/Cargo.lock b/Cargo.lock index 7fe4380b..a2e57781 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,6 +493,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +[[package]] +name = "cli-debugger" +version = "0.1.0" +dependencies = [ + "clap", + "debugger-session", + "faster-hex 0.10.0", + "kaspa-consensus-core", + "kaspa-txscript", + "kaspa-txscript-errors", + "serde_json", + "silverscript-lang", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -606,6 +620,20 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "debugger-session" +version = "0.1.0" +dependencies = [ + "faster-hex 0.10.0", + "kaspa-addresses", + "kaspa-consensus-core", + "kaspa-txscript", + "kaspa-txscript-errors", + "serde", + "serde_json", + "silverscript-lang", +] + [[package]] name = "deranged" version = "0.5.5" diff --git a/Cargo.toml b/Cargo.toml index ddfd4973..e300c0bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,10 @@ [workspace] -members = ["silverscript-lang", "covenants/sdk"] +members = [ + "silverscript-lang", + "debugger/session", + "debugger/cli", + "covenants/sdk", +] resolver = "2" [workspace.package] diff --git a/debugger/cli/Cargo.toml b/debugger/cli/Cargo.toml new file mode 100644 index 00000000..3c3d1b78 --- /dev/null +++ b/debugger/cli/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "cli-debugger" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +repository.workspace = true +rust-version.workspace = true + +[[bin]] +name = "cli-debugger" +path = "src/main.rs" + +[dependencies] +debugger-session = { path = "../session" } +silverscript-lang = { path = "../../silverscript-lang" } +kaspa-consensus-core.workspace = true +kaspa-txscript.workspace = true +kaspa-txscript-errors.workspace = true +clap = { version = "4.5.60", features = ["derive"] } +faster-hex = "0.10" +serde_json = "1.0" diff --git a/silverscript-lang/src/bin/sil-debug.rs b/debugger/cli/src/main.rs similarity index 99% rename from silverscript-lang/src/bin/sil-debug.rs rename to debugger/cli/src/main.rs index 8fcd602f..1c50e116 100644 --- a/silverscript-lang/src/bin/sil-debug.rs +++ b/debugger/cli/src/main.rs @@ -6,15 +6,15 @@ use kaspa_consensus_core::hashing::sighash::SigHashReusedValuesUnsync; use kaspa_txscript::caches::Cache; use kaspa_txscript::{EngineCtx, EngineFlags}; +use debugger_session::session::{DebugEngine, DebugSession}; use silverscript_lang::ast::{Expr, ExprKind, parse_contract_ast}; use silverscript_lang::compiler::{CompileOptions, compile_contract}; -use silverscript_lang::debug::session::{DebugEngine, DebugSession}; use silverscript_lang::span; const PROMPT: &str = "(sdb) "; #[derive(Debug, Parser)] -#[command(name = "sil-debug", about = "SilverScript debugger")] +#[command(name = "cli-debugger", about = "SilverScript debugger")] struct CliArgs { script_path: String, #[arg(long = "no-selector")] diff --git a/silverscript-lang/tests/debugger_cli_tests.rs b/debugger/cli/tests/cli_tests.rs similarity index 80% rename from silverscript-lang/tests/debugger_cli_tests.rs rename to debugger/cli/tests/cli_tests.rs index ba7d99ab..31d76882 100644 --- a/silverscript-lang/tests/debugger_cli_tests.rs +++ b/debugger/cli/tests/cli_tests.rs @@ -4,15 +4,15 @@ use std::process::{Command, Stdio}; fn example_contract_path() -> PathBuf { let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - manifest_dir.join("tests/examples/if_statement.sil") + manifest_dir.join("tests/if_statement.sil") } #[test] -fn sil_debug_repl_all_commands_smoke() { +fn cli_debugger_repl_all_commands_smoke() { let contract_path = example_contract_path(); assert!(contract_path.exists(), "example contract not found: {}", contract_path.display()); - let mut child = Command::new(env!("CARGO_BIN_EXE_sil-debug")) + let mut child = Command::new(env!("CARGO_BIN_EXE_cli-debugger")) .arg(contract_path) .arg("--function") .arg("hello") @@ -28,13 +28,13 @@ fn sil_debug_repl_all_commands_smoke() { .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() - .expect("failed to spawn sil-debug"); + .expect("failed to spawn cli-debugger"); let input = b"help\nl\nstack\nb 1\nb 7\nb\nn\nsi\nq\n"; child.stdin.as_mut().expect("stdin available").write_all(input).expect("write stdin"); - let output = child.wait_with_output().expect("wait for sil-debug"); - assert!(output.status.success(), "sil-debug exited with status {:?}", output.status.code()); + let output = child.wait_with_output().expect("wait for cli-debugger"); + assert!(output.status.success(), "cli-debugger exited with status {:?}", output.status.code()); let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); diff --git a/debugger/cli/tests/if_statement.sil b/debugger/cli/tests/if_statement.sil new file mode 100644 index 00000000..8331be55 --- /dev/null +++ b/debugger/cli/tests/if_statement.sil @@ -0,0 +1,17 @@ +pragma silverscript ^0.1.0; + +contract IfStatement(int x, int y) { + entrypoint function hello(int a, int b) { + int d = a + b; + d = d - a; + if (d == x - 2) { + int c = d + b; + d = a + c; + require(c > d); + } else { + require(d == a); + } + d = d + a; + require(d == y); + } +} diff --git a/debugger/session/Cargo.toml b/debugger/session/Cargo.toml new file mode 100644 index 00000000..76fa8405 --- /dev/null +++ b/debugger/session/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "debugger-session" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +repository.workspace = true +rust-version.workspace = true + +[lib] +name = "debugger_session" +path = "src/lib.rs" + +[dependencies] +silverscript-lang = { path = "../../silverscript-lang" } +kaspa-consensus-core.workspace = true +kaspa-txscript.workspace = true +kaspa-txscript-errors.workspace = true +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +faster-hex = "0.10" + +[dev-dependencies] +kaspa-addresses.workspace = true diff --git a/debugger/session/src/lib.rs b/debugger/session/src/lib.rs new file mode 100644 index 00000000..0d9cebd9 --- /dev/null +++ b/debugger/session/src/lib.rs @@ -0,0 +1,2 @@ +pub mod presentation; +pub mod session; diff --git a/silverscript-lang/src/debug/presentation.rs b/debugger/session/src/presentation.rs similarity index 98% rename from silverscript-lang/src/debug/presentation.rs rename to debugger/session/src/presentation.rs index 3b052e62..65ce7100 100644 --- a/silverscript-lang/src/debug/presentation.rs +++ b/debugger/session/src/presentation.rs @@ -1,5 +1,6 @@ -use crate::debug::SourceSpan; -use crate::debug::session::DebugValue; +use silverscript_lang::debug_info::SourceSpan; + +use crate::session::DebugValue; #[derive(Debug, Clone)] pub struct SourceContextLine { diff --git a/silverscript-lang/src/debug/session.rs b/debugger/session/src/session.rs similarity index 98% rename from silverscript-lang/src/debug/session.rs rename to debugger/session/src/session.rs index 63ebce19..589b158b 100644 --- a/silverscript-lang/src/debug/session.rs +++ b/debugger/session/src/session.rs @@ -8,12 +8,14 @@ use kaspa_txscript::script_builder::ScriptBuilder; use kaspa_txscript::{DynOpcodeImplementation, EngineCtx, EngineFlags, TxScriptEngine, parse_script}; use serde::{Deserialize, Serialize}; -use crate::ast::{Expr, ExprKind}; -use crate::compiler::compile_debug_expr; -use crate::debug::presentation::{build_source_context, format_value as format_debug_value}; -use crate::debug::{DebugFunctionRange, DebugInfo, DebugMapping, DebugParamMapping, DebugVariableUpdate, MappingKind, SourceSpan}; +use silverscript_lang::ast::{Expr, ExprKind}; +use silverscript_lang::compiler::compile_debug_expr; +use silverscript_lang::debug_info::{ + DebugFunctionRange, DebugInfo, DebugMapping, DebugParamMapping, DebugVariableUpdate, MappingKind, SourceSpan, +}; -pub use crate::debug::presentation::{SourceContext, SourceContextLine}; +pub use crate::presentation::{SourceContext, SourceContextLine}; +use crate::presentation::{build_source_context, format_value as format_debug_value}; pub type DebugTx<'a> = PopulatedTransaction<'a>; pub type DebugReused = SigHashReusedValuesUnsync; @@ -875,9 +877,9 @@ fn encode_hex(bytes: &[u8]) -> String { mod tests { use super::*; - use crate::ast::{BinaryOp, Expr, ExprKind}; - use crate::debug::{DebugConstantMapping, DebugFunctionRange, DebugInfo, DebugParamMapping, DebugVariableUpdate}; - use crate::span; + use silverscript_lang::ast::{BinaryOp, Expr, ExprKind}; + use silverscript_lang::debug_info::{DebugConstantMapping, DebugFunctionRange, DebugInfo, DebugParamMapping, DebugVariableUpdate}; + use silverscript_lang::span; fn make_session( params: Vec, diff --git a/silverscript-lang/tests/debug_session_tests.rs b/debugger/session/tests/debug_session_tests.rs similarity index 98% rename from silverscript-lang/tests/debug_session_tests.rs rename to debugger/session/tests/debug_session_tests.rs index ae15adc2..eb358638 100644 --- a/silverscript-lang/tests/debug_session_tests.rs +++ b/debugger/session/tests/debug_session_tests.rs @@ -14,10 +14,10 @@ use kaspa_txscript::covenants::CovenantsContext; use kaspa_txscript::opcodes::codes::OpTrue; use kaspa_txscript::{EngineCtx, EngineFlags}; +use debugger_session::session::{DebugSession, ShadowTxContext}; use silverscript_lang::ast::{Expr, parse_contract_ast}; use silverscript_lang::compiler::{CompileOptions, compile_contract}; -use silverscript_lang::debug::MappingKind; -use silverscript_lang::debug::session::{DebugSession, ShadowTxContext}; +use silverscript_lang::debug_info::MappingKind; fn example_contract_path() -> PathBuf { let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -60,7 +60,7 @@ where let ctx = EngineCtx::new(&sig_cache).with_reused(&reused_values); let flags = EngineFlags { covenants_enabled: true }; - let engine = silverscript_lang::debug::session::DebugEngine::new(ctx, flags); + let engine = debugger_session::session::DebugEngine::new(ctx, flags); let entry = compiled .abi @@ -759,7 +759,7 @@ contract CovLocal() { let ctx = EngineCtx::new(&sig_cache).with_reused(&reused_values).with_covenants_ctx(&cov_ctx); let input_ref = &tx.inputs[0]; let utxo_ref = populated_tx.utxo(0).ok_or("missing utxo for input 0")?; - let engine = silverscript_lang::debug::session::DebugEngine::from_transaction_input( + let engine = debugger_session::session::DebugEngine::from_transaction_input( &populated_tx, input_ref, 0, diff --git a/debugger/session/tests/examples/debug_messages.sil b/debugger/session/tests/examples/debug_messages.sil new file mode 100644 index 00000000..35407568 --- /dev/null +++ b/debugger/session/tests/examples/debug_messages.sil @@ -0,0 +1,8 @@ +pragma silverscript ^0.1.0; + +contract DebugMessages() { + entrypoint function spend(int value) { + require(value == 1, "Wrong value passed"); + require(value + 1 == 2, "Sum doesn't work"); + } +} diff --git a/debugger/session/tests/examples/if_statement.sil b/debugger/session/tests/examples/if_statement.sil new file mode 100644 index 00000000..8331be55 --- /dev/null +++ b/debugger/session/tests/examples/if_statement.sil @@ -0,0 +1,17 @@ +pragma silverscript ^0.1.0; + +contract IfStatement(int x, int y) { + entrypoint function hello(int a, int b) { + int d = a + b; + d = d - a; + if (d == x - 2) { + int c = d + b; + d = a + c; + require(c > d); + } else { + require(d == a); + } + d = d + a; + require(d == y); + } +} diff --git a/silverscript-lang/src/compiler.rs b/silverscript-lang/src/compiler.rs index 72e52bca..1e12962d 100644 --- a/silverscript-lang/src/compiler.rs +++ b/silverscript-lang/src/compiler.rs @@ -9,8 +9,8 @@ use crate::ast::{ StateBindingAst, StateFieldExpr, Statement, TimeVar, TypeBase, TypeRef, UnaryOp, UnarySuffixKind, parse_contract_ast, parse_type_ref, }; -use crate::debug::labels::synthetic; -use crate::debug::{DebugInfo, SourceSpan}; +use crate::debug_info::labels::synthetic; +use crate::debug_info::{DebugInfo, SourceSpan}; pub use crate::errors::{CompilerError, ErrorSpan}; use crate::span; diff --git a/silverscript-lang/src/compiler/debug_recording.rs b/silverscript-lang/src/compiler/debug_recording.rs index e6ba2c6f..eb08ffd0 100644 --- a/silverscript-lang/src/compiler/debug_recording.rs +++ b/silverscript-lang/src/compiler/debug_recording.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use kaspa_txscript::script_builder::ScriptBuilder; use crate::ast::{ContractFieldAst, Expr, FunctionAst, ParamAst, Statement}; -use crate::debug::{ +use crate::debug_info::{ DebugConstantMapping, DebugEvent, DebugEventKind, DebugFunctionRange, DebugInfo, DebugParamMapping, DebugRecorder, DebugVariableUpdate, SourceSpan, }; diff --git a/silverscript-lang/src/debug.rs b/silverscript-lang/src/debug_info.rs similarity index 99% rename from silverscript-lang/src/debug.rs rename to silverscript-lang/src/debug_info.rs index 1514ed93..16febeac 100644 --- a/silverscript-lang/src/debug.rs +++ b/silverscript-lang/src/debug_info.rs @@ -2,9 +2,6 @@ use crate::ast::Expr; use crate::span; use serde::{Deserialize, Serialize}; -pub mod presentation; -pub mod session; - #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] pub struct SourceSpan { pub line: u32, diff --git a/silverscript-lang/src/lib.rs b/silverscript-lang/src/lib.rs index cdd68dfb..d1423e0e 100644 --- a/silverscript-lang/src/lib.rs +++ b/silverscript-lang/src/lib.rs @@ -1,6 +1,6 @@ pub mod ast; pub mod compiler; -pub mod debug; +pub mod debug_info; pub mod diagnostic; pub mod errors; pub mod parser; From b51ee1e196002621444bd42d23d23e7a64d909ab Mon Sep 17 00:00:00 2001 From: Romain Billot Date: Thu, 26 Feb 2026 16:23:15 +0100 Subject: [PATCH 5/5] spanned ast, spanned error, domain diagnostics, initial extensions, more granular ast nodes (#40) * wip: spanned ast, syntaxe highlights and minor refactoring in preparation of lsp * fix: zed repo path * fix: vscode * feat: parser diagnostic * fix: base pest error on unclassified diagnostic * feat(ts): granular parsing on introspection expression * feat(extensions): auto closing brackets and indentation * bump(extension): zed * chore(extension): build tool and prepare publish * fix(extensions/vscode): keep ts wasm dep * fix: conflicts * bump: extensions * self review refacto * test: remove test that isn't relevant anymore * cargo fmt * chore: zed revision bump * review: git ignore vscode ts wasm build * review: update tree sitter - fix os path * review(silverc): use clap and rename ast options * fix(silverc): ast only option typo * review: add todo annotation to unsupported intr kind * review: revert abi naming at contract level * review: use byte array instead of re-defining logic again * review: add test comment on expected failure for introspection root * review(ts): add examples smoke tests and fix reverse parsing issue * review: revert compile stmt assign * review(cli): default behaviors enhancement, improve help text and more tests * review: test wording * review(tree-sitter): fix repository url * review: try to reduce diff frictions * feat(highlight): op codes, new calls and methods calls * review(cli): default ast output is file with suffix * test: fix with new ast default * review: compile exp empty array test and todo anotation * review: compile_length_expr is responsible for argument count validation * clippy * adjust silverc test regarding double argument usage * Revert "review: compile_length_expr is responsible for argument count validation" This reverts commit c9bb5304810630c66b4a19354cfd65b6983a7f22. --------- Co-authored-by: IzioDev <9900846+IzioDev@users.noreply.github.com> --- Cargo.lock | 127 + Cargo.toml | 1 + extensions/silverscript.nvim/README.md | 26 + .../silverscript.nvim/lua/silverscript.lua | 56 + .../silverscript.nvim/plugin/silverscript.lua | 1 + .../queries/silverscript/brackets.scm | 6 + .../queries/silverscript/highlights.scm | 126 + extensions/vscode/.gitignore | 2 + extensions/vscode/.vscode-test.mjs | 5 + extensions/vscode/.vscode/extensions.json | 9 + extensions/vscode/.vscode/launch.json | 14 + extensions/vscode/.vscode/settings.json | 13 + extensions/vscode/.vscode/tasks.json | 58 + extensions/vscode/.vscodeignore | 19 + extensions/vscode/CHANGELOG.md | 9 + extensions/vscode/LICENSE | 15 + extensions/vscode/README.md | 24 + extensions/vscode/assets/.gitignore | 1 + extensions/vscode/assets/.gitkeep | 0 extensions/vscode/esbuild.js | 56 + extensions/vscode/eslint.config.mjs | 33 + extensions/vscode/language-configuration.json | 19 + extensions/vscode/package-lock.json | 8911 ++++++++++ extensions/vscode/package.json | 97 + extensions/vscode/queries/highlights.scm | 126 + extensions/vscode/src/extension.ts | 397 + extensions/vscode/tsconfig.json | 11 + extensions/zed/.gitignore | 1 + extensions/zed/README.md | 24 + extensions/zed/extension.toml | 19 + .../zed/languages/silverscript/config.toml | 17 + .../zed/languages/silverscript/highlights.scm | 126 + .../zed/languages/silverscript/indents.scm | 8 + silverscript-lang/Cargo.toml | 1 + silverscript-lang/src/ast.rs | 1346 +- silverscript-lang/src/bin/silverc.rs | 148 +- silverscript-lang/src/compiler.rs | 3137 ++-- silverscript-lang/src/diagnostic/mod.rs | 5 + silverscript-lang/src/diagnostic/parse.rs | 217 + .../src/diagnostic/parse_diagnostics.rs | 178 + silverscript-lang/src/errors.rs | 52 + silverscript-lang/src/lib.rs | 3 + silverscript-lang/src/parser.rs | 18 +- silverscript-lang/src/span.rs | 81 + .../tests/ast_json/require_test.ast.json | 2 +- .../tests/ast_json/yield_test.ast.json | 2 +- silverscript-lang/tests/ast_json_tests.rs | 2 +- silverscript-lang/tests/ast_spans_tests.rs | 60 + .../tests/cashc_valid_examples_tests.rs | 4 +- silverscript-lang/tests/compiler_tests.rs | 113 +- silverscript-lang/tests/date_literal_tests.rs | 8 +- .../tests/parse_diagnostics_tests.rs | 53 + silverscript-lang/tests/parser_tests.rs | 22 + silverscript-lang/tests/silverc_tests.rs | 109 +- .../tests/tutorial_rust_examples_tests.rs | 2 +- tree-sitter/.editorconfig | 50 + tree-sitter/.gitattributes | 46 + tree-sitter/.gitignore | 48 + tree-sitter/CMakeLists.txt | 76 + tree-sitter/Cargo.lock | 216 + tree-sitter/Cargo.toml | 34 + tree-sitter/Makefile | 115 + tree-sitter/Package.swift | 41 + tree-sitter/README.md | 10 + tree-sitter/binding.gyp | 35 + .../bindings/c/tree-sitter-silverscript.pc.in | 10 + .../c/tree_sitter/tree-sitter-silverscript.h | 16 + tree-sitter/bindings/go/binding.go | 15 + tree-sitter/bindings/go/binding_test.go | 15 + tree-sitter/bindings/node/binding.cc | 19 + tree-sitter/bindings/node/binding_test.js | 11 + tree-sitter/bindings/node/index.d.ts | 60 + tree-sitter/bindings/node/index.js | 42 + .../bindings/python/tests/test_binding.py | 12 + .../tree_sitter_silverscript/__init__.py | 54 + .../tree_sitter_silverscript/__init__.pyi | 17 + .../python/tree_sitter_silverscript/binding.c | 35 + .../python/tree_sitter_silverscript/py.typed | 0 tree-sitter/bindings/rust/build.rs | 50 + tree-sitter/bindings/rust/lib.rs | 59 + .../TreeSitterSilverscript/silverscript.h | 16 + .../TreeSitterSilverscriptTests.swift | 12 + tree-sitter/go.mod | 5 + tree-sitter/grammar.js | 438 + tree-sitter/package-lock.json | 382 + tree-sitter/package.json | 64 + tree-sitter/pyproject.toml | 30 + tree-sitter/queries/highlights.scm | 126 + tree-sitter/scripts/sync-highlights.mjs | 44 + tree-sitter/scripts/sync-vscode-wasm.mjs | 30 + tree-sitter/scripts/sync-zed-wasm.mjs | 30 + tree-sitter/setup.py | 77 + tree-sitter/src/grammar.json | 2469 +++ tree-sitter/src/node-types.json | 1806 ++ tree-sitter/src/parser.c | 13869 ++++++++++++++++ tree-sitter/src/tree_sitter/alloc.h | 54 + tree-sitter/src/tree_sitter/array.h | 347 + tree-sitter/src/tree_sitter/parser.h | 286 + .../tests/examples_parse_smoke_test.rs | 50 + tree-sitter/tree-sitter.json | 37 + 100 files changed, 35220 insertions(+), 1958 deletions(-) create mode 100644 extensions/silverscript.nvim/README.md create mode 100644 extensions/silverscript.nvim/lua/silverscript.lua create mode 100644 extensions/silverscript.nvim/plugin/silverscript.lua create mode 100644 extensions/silverscript.nvim/queries/silverscript/brackets.scm create mode 100644 extensions/silverscript.nvim/queries/silverscript/highlights.scm create mode 100644 extensions/vscode/.gitignore create mode 100644 extensions/vscode/.vscode-test.mjs create mode 100644 extensions/vscode/.vscode/extensions.json create mode 100644 extensions/vscode/.vscode/launch.json create mode 100644 extensions/vscode/.vscode/settings.json create mode 100644 extensions/vscode/.vscode/tasks.json create mode 100644 extensions/vscode/.vscodeignore create mode 100644 extensions/vscode/CHANGELOG.md create mode 100644 extensions/vscode/LICENSE create mode 100644 extensions/vscode/README.md create mode 100644 extensions/vscode/assets/.gitignore create mode 100644 extensions/vscode/assets/.gitkeep create mode 100644 extensions/vscode/esbuild.js create mode 100644 extensions/vscode/eslint.config.mjs create mode 100644 extensions/vscode/language-configuration.json create mode 100644 extensions/vscode/package-lock.json create mode 100644 extensions/vscode/package.json create mode 100644 extensions/vscode/queries/highlights.scm create mode 100644 extensions/vscode/src/extension.ts create mode 100644 extensions/vscode/tsconfig.json create mode 100644 extensions/zed/.gitignore create mode 100644 extensions/zed/README.md create mode 100644 extensions/zed/extension.toml create mode 100644 extensions/zed/languages/silverscript/config.toml create mode 100644 extensions/zed/languages/silverscript/highlights.scm create mode 100644 extensions/zed/languages/silverscript/indents.scm create mode 100644 silverscript-lang/src/diagnostic/mod.rs create mode 100644 silverscript-lang/src/diagnostic/parse.rs create mode 100644 silverscript-lang/src/diagnostic/parse_diagnostics.rs create mode 100644 silverscript-lang/src/errors.rs create mode 100644 silverscript-lang/src/span.rs create mode 100644 silverscript-lang/tests/ast_spans_tests.rs create mode 100644 silverscript-lang/tests/parse_diagnostics_tests.rs create mode 100644 tree-sitter/.editorconfig create mode 100644 tree-sitter/.gitattributes create mode 100644 tree-sitter/.gitignore create mode 100644 tree-sitter/CMakeLists.txt create mode 100644 tree-sitter/Cargo.lock create mode 100644 tree-sitter/Cargo.toml create mode 100644 tree-sitter/Makefile create mode 100644 tree-sitter/Package.swift create mode 100644 tree-sitter/README.md create mode 100644 tree-sitter/binding.gyp create mode 100644 tree-sitter/bindings/c/tree-sitter-silverscript.pc.in create mode 100644 tree-sitter/bindings/c/tree_sitter/tree-sitter-silverscript.h create mode 100644 tree-sitter/bindings/go/binding.go create mode 100644 tree-sitter/bindings/go/binding_test.go create mode 100644 tree-sitter/bindings/node/binding.cc create mode 100644 tree-sitter/bindings/node/binding_test.js create mode 100644 tree-sitter/bindings/node/index.d.ts create mode 100644 tree-sitter/bindings/node/index.js create mode 100644 tree-sitter/bindings/python/tests/test_binding.py create mode 100644 tree-sitter/bindings/python/tree_sitter_silverscript/__init__.py create mode 100644 tree-sitter/bindings/python/tree_sitter_silverscript/__init__.pyi create mode 100644 tree-sitter/bindings/python/tree_sitter_silverscript/binding.c create mode 100644 tree-sitter/bindings/python/tree_sitter_silverscript/py.typed create mode 100644 tree-sitter/bindings/rust/build.rs create mode 100644 tree-sitter/bindings/rust/lib.rs create mode 100644 tree-sitter/bindings/swift/TreeSitterSilverscript/silverscript.h create mode 100644 tree-sitter/bindings/swift/TreeSitterSilverscriptTests/TreeSitterSilverscriptTests.swift create mode 100644 tree-sitter/go.mod create mode 100644 tree-sitter/grammar.js create mode 100644 tree-sitter/package-lock.json create mode 100644 tree-sitter/package.json create mode 100644 tree-sitter/pyproject.toml create mode 100644 tree-sitter/queries/highlights.scm create mode 100644 tree-sitter/scripts/sync-highlights.mjs create mode 100644 tree-sitter/scripts/sync-vscode-wasm.mjs create mode 100644 tree-sitter/scripts/sync-zed-wasm.mjs create mode 100644 tree-sitter/setup.py create mode 100644 tree-sitter/src/grammar.json create mode 100644 tree-sitter/src/node-types.json create mode 100644 tree-sitter/src/parser.c create mode 100644 tree-sitter/src/tree_sitter/alloc.h create mode 100644 tree-sitter/src/tree_sitter/array.h create mode 100644 tree-sitter/src/tree_sitter/parser.h create mode 100644 tree-sitter/tests/examples_parse_smoke_test.rs create mode 100644 tree-sitter/tree-sitter.json diff --git a/Cargo.lock b/Cargo.lock index e7b610eb..f93e713f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,6 +39,56 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "anyhow" version = "1.0.100" @@ -397,6 +447,52 @@ dependencies = [ "windows-link", ] +[[package]] +name = "clap" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -858,6 +954,12 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -964,6 +1066,12 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" version = "0.11.0" @@ -1504,6 +1612,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "option-ext" version = "0.2.0" @@ -2078,6 +2192,7 @@ version = "0.1.0" dependencies = [ "blake2b_simd", "chrono", + "clap", "kaspa-addresses", "kaspa-consensus-core", "kaspa-txscript", @@ -2112,6 +2227,12 @@ dependencies = [ "serde", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -2373,6 +2494,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index ddfd4973..810cc489 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = ["silverscript-lang", "covenants/sdk"] +exclude = ["tree-sitter"] resolver = "2" [workspace.package] diff --git a/extensions/silverscript.nvim/README.md b/extensions/silverscript.nvim/README.md new file mode 100644 index 00000000..b9d7cadf --- /dev/null +++ b/extensions/silverscript.nvim/README.md @@ -0,0 +1,26 @@ +Requirements: + +- nvim-treesitter +- nvim-lspconfig (optional, for LSP) + +Lazy plugin: + +```lua +{ + "kaspanet/silverscript", + dependencies = { "nvim-treesitter/nvim-treesitter" }, + init = function(plugin) + vim.opt.rtp:append(plugin.dir .. "/extensions/silverscript.nvim") + end, + config = function() + require("silverscript").setup({ + lsp = { + cmd = { "silverscript-lsp" }, + filetypes = { "silverscript" }, + }, + }) + end, +} +``` + +- After install, run :TSInstall silverscript (or add it to ensure_installed) so Tree‑sitter builds the parser. diff --git a/extensions/silverscript.nvim/lua/silverscript.lua b/extensions/silverscript.nvim/lua/silverscript.lua new file mode 100644 index 00000000..96897f1c --- /dev/null +++ b/extensions/silverscript.nvim/lua/silverscript.lua @@ -0,0 +1,56 @@ +local M = {} + +function M.setup(opts) + opts = opts or {} + local enable_lsp = opts.enable_lsp ~= false + + vim.filetype.add({ extension = { sil = "silverscript" } }) + + local parser_config = require("nvim-treesitter.parsers").get_parser_configs() + + -- For actual deployment + parser_config.silverscript = { + install_info = { + url = "https://github.com/kaspanet/silverscript", + files = { "src/parser.c" }, + branch = "main", + location = 'tree-sitter', + }, + filetype = "silverscript", + } + + -- Dev mode only + -- parser_config.silverscript = { + -- install_info = { + -- url = "/mnt/d/Dev/kaspa/silverscript", + -- location = "tree-sitter", + -- files = { "src/parser.c" }, + -- }, + -- filetype = "silverscript", + -- } + + if enable_lsp then + local ok, lspconfig = pcall(require, "lspconfig") + if ok then + local configs = require("lspconfig.configs") + if not configs.silverscript then + configs.silverscript = { + default_config = { + cmd = { "silverscript-lsp" }, + filetypes = { "silverscript" }, + root_dir = lspconfig.util.root_pattern("Cargo.toml", ".git"), + settings = { + silverscript = { + covenantsEnabled = true, + withoutSelector = false, + }, + }, + }, + } + end + lspconfig.silverscript.setup(opts.lsp or {}) + end + end +end + +return M diff --git a/extensions/silverscript.nvim/plugin/silverscript.lua b/extensions/silverscript.nvim/plugin/silverscript.lua new file mode 100644 index 00000000..b34df46b --- /dev/null +++ b/extensions/silverscript.nvim/plugin/silverscript.lua @@ -0,0 +1 @@ +require("silverscript").setup() diff --git a/extensions/silverscript.nvim/queries/silverscript/brackets.scm b/extensions/silverscript.nvim/queries/silverscript/brackets.scm new file mode 100644 index 00000000..5282d8ec --- /dev/null +++ b/extensions/silverscript.nvim/queries/silverscript/brackets.scm @@ -0,0 +1,6 @@ +("{" @open "}" @close) +("[" @open "]" @close) +("(" @open ")" @close) + +("\"" @open "\"" @close) +("'" @open "'" @close) diff --git a/extensions/silverscript.nvim/queries/silverscript/highlights.scm b/extensions/silverscript.nvim/queries/silverscript/highlights.scm new file mode 100644 index 00000000..d730b378 --- /dev/null +++ b/extensions/silverscript.nvim/queries/silverscript/highlights.scm @@ -0,0 +1,126 @@ +(comment) @comment + +(string_literal) @string + +(number_literal) @number + +(hex_literal) @number + +(boolean_literal) @boolean + +(date_literal) @function.builtin + +(type_name) @type + +(instantiation + (identifier) @type.builtin + (#match? @type.builtin + "^(LockingBytecodeNullData|ScriptPubKeyP2PK|ScriptPubKeyP2SH|ScriptPubKeyP2SHFromRedeemScript)$")) + +(instantiation + (identifier) @type) + +(contract_definition + name: (identifier) @type) + +(function_definition + name: (identifier) @function) + +(constant_definition + name: (identifier) @constant) + +(contract_field_definition + name: (identifier) @property) + +(variable_definition + name: (identifier) @variable) + +(parameter + (identifier) @variable.parameter) + +(tx_var) @variable.builtin + +(nullary_op) @variable.builtin + +(output_root) @variable.builtin + +(input_root) @variable.builtin + +(tuple_index + "[" @operator + "]" @operator) + +(output_field + "." @operator) + +(input_field + "." @operator) + +(output_field_name) @property + +(input_field_name) @property + +(state_entry + (identifier) @property) + +(state_typed_binding + (identifier) @property + ":" + (type_name) + (identifier) @variable) + +(function_call + (identifier) @function.builtin + (#match? @function.builtin + "^(readInputState|validateOutputState|verifyOutputState|verifyOutputStates|OpSha256|sha256|OpTxSubnetId|OpTxGas|OpTxPayloadLen|OpTxPayloadSubstr|OpOutpointTxId|OpOutpointIndex|OpTxInputScriptSigLen|OpTxInputScriptSigSubstr|OpTxInputSeq|OpTxInputIsCoinbase|OpTxInputSpkLen|OpTxInputSpkSubstr|OpTxOutputSpkLen|OpTxOutputSpkSubstr|OpAuthOutputCount|OpAuthOutputIdx|OpInputCovenantId|OpCovInputCount|OpCovInputIdx|OpCovOutCount|OpCovOutputIdx|OpNum2Bin|OpBin2Num|OpChainblockSeqCommit|checkDataSig|checkSig|checkMultiSig|blake2b)$")) + +(unary_suffix) @property + +(split_call + ".split" @function.method) + +(slice_call + ".slice" @function.method) + +(reverse_call + ".reverse" @function.method) + +(array_bound) @number + +[ + "pragma" + "silverscript" + "contract" + "entrypoint" + "function" + "constant" + "if" + "else" + "for" + "new" + "require" + "return" + "yield" + "console.log" +] @keyword + +[ + "||" + "&&" + "==" + "!=" + "<" + "<=" + ">" + ">=" + "+" + "-" + "*" + "/" + "%" + "!" + "&" + "|" + "^" + "=" +] @operator diff --git a/extensions/vscode/.gitignore b/extensions/vscode/.gitignore new file mode 100644 index 00000000..f06235c4 --- /dev/null +++ b/extensions/vscode/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/extensions/vscode/.vscode-test.mjs b/extensions/vscode/.vscode-test.mjs new file mode 100644 index 00000000..b62ba25f --- /dev/null +++ b/extensions/vscode/.vscode-test.mjs @@ -0,0 +1,5 @@ +import { defineConfig } from '@vscode/test-cli'; + +export default defineConfig({ + files: 'out/test/**/*.test.js', +}); diff --git a/extensions/vscode/.vscode/extensions.json b/extensions/vscode/.vscode/extensions.json new file mode 100644 index 00000000..cbd98c9f --- /dev/null +++ b/extensions/vscode/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "dbaeumer.vscode-eslint", + "connor4312.esbuild-problem-matchers", + "ms-vscode.extension-test-runner", + ], +} diff --git a/extensions/vscode/.vscode/launch.json b/extensions/vscode/.vscode/launch.json new file mode 100644 index 00000000..fafb95fe --- /dev/null +++ b/extensions/vscode/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/dist/**/*.js"], + "preLaunchTask": "${defaultBuildTask}", + "sourceMaps": true + } + ] +} diff --git a/extensions/vscode/.vscode/settings.json b/extensions/vscode/.vscode/settings.json new file mode 100644 index 00000000..e0a4cfb2 --- /dev/null +++ b/extensions/vscode/.vscode/settings.json @@ -0,0 +1,13 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.exclude": { + "out": false, // set this to true to hide the "out" folder with the compiled JS files + "dist": false, // set this to true to hide the "dist" folder with the compiled JS files + }, + "search.exclude": { + "out": true, // set this to false to include "out" folder in search results + "dist": true, // set this to false to include "dist" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off", +} diff --git a/extensions/vscode/.vscode/tasks.json b/extensions/vscode/.vscode/tasks.json new file mode 100644 index 00000000..1858572e --- /dev/null +++ b/extensions/vscode/.vscode/tasks.json @@ -0,0 +1,58 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "label": "watch", + "dependsOn": ["npm: watch:tsc", "npm: watch:esbuild"], + "presentation": { + "reveal": "never", + }, + "group": { + "kind": "build", + "isDefault": true, + }, + }, + { + "type": "npm", + "script": "watch:esbuild", + "group": "build", + "problemMatcher": "$esbuild-watch", + "isBackground": true, + "label": "npm: watch:esbuild", + "presentation": { + "group": "watch", + "reveal": "never", + }, + }, + { + "type": "npm", + "script": "watch:tsc", + "group": "build", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "label": "npm: watch:tsc", + "presentation": { + "group": "watch", + "reveal": "never", + }, + }, + { + "type": "npm", + "script": "watch-tests", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never", + "group": "watchers", + }, + "group": "build", + }, + { + "label": "tasks: watch-tests", + "dependsOn": ["npm: watch", "npm: watch-tests"], + "problemMatcher": [], + }, + ], +} diff --git a/extensions/vscode/.vscodeignore b/extensions/vscode/.vscodeignore new file mode 100644 index 00000000..ba7a4413 --- /dev/null +++ b/extensions/vscode/.vscodeignore @@ -0,0 +1,19 @@ +.vscode/** +.vscode-test/** +out/** +node_modules/** +src/** +.gitignore +.yarnrc +esbuild.js +vsc-extension-quickstart.md +**/tsconfig.json +**/eslint.config.mjs +**/*.map +**/*.ts +**/.vscode-test.* + +# keep these +!assets/** +!queries/** +!node_modules/web-tree-sitter/** diff --git a/extensions/vscode/CHANGELOG.md b/extensions/vscode/CHANGELOG.md new file mode 100644 index 00000000..4069c280 --- /dev/null +++ b/extensions/vscode/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +All notable changes to the "silverscript" extension will be documented in this file. + +Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. + +## [Unreleased] + +- Initial release diff --git a/extensions/vscode/LICENSE b/extensions/vscode/LICENSE new file mode 100644 index 00000000..a4814c76 --- /dev/null +++ b/extensions/vscode/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2026 Kaspa developers + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/extensions/vscode/README.md b/extensions/vscode/README.md new file mode 100644 index 00000000..ec38b2bb --- /dev/null +++ b/extensions/vscode/README.md @@ -0,0 +1,24 @@ +### Pre-release + +`npm exec vsce package -- --pre-release` + +### Development + +- Requirement: Node.js 22+. +- In `extensions/vscode`, install dependencies with `npm i`. +- Build the extension once with `npm run compile` (or keep it rebuilding with `npm run watch`). +- Open `extensions/vscode` in VS Code. +- Press `F5` and run `Run Extension` to start an Extension Development Host with this extension loaded. + +#### Live Grammar Changes + +Build the grammar from your working tree and sync the WASM used by the VS Code extension: + +```bash +cd tree-sitter +npm run build:vscode +``` + +This also refreshes shared highlighting queries (`extensions/vscode/queries/highlights.scm`). + +Then in the Extension Development Host, press `Ctrl+R` to reload and apply parser/query updates. diff --git a/extensions/vscode/assets/.gitignore b/extensions/vscode/assets/.gitignore new file mode 100644 index 00000000..1c5ea848 --- /dev/null +++ b/extensions/vscode/assets/.gitignore @@ -0,0 +1 @@ +tree-sitter-silverscript.wasm diff --git a/extensions/vscode/assets/.gitkeep b/extensions/vscode/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/extensions/vscode/esbuild.js b/extensions/vscode/esbuild.js new file mode 100644 index 00000000..b4395aab --- /dev/null +++ b/extensions/vscode/esbuild.js @@ -0,0 +1,56 @@ +const esbuild = require("esbuild"); + +const production = process.argv.includes("--production"); +const watch = process.argv.includes("--watch"); + +/** + * @type {import('esbuild').Plugin} + */ +const esbuildProblemMatcherPlugin = { + name: "esbuild-problem-matcher", + + setup(build) { + build.onStart(() => { + console.log("[watch] build started"); + }); + build.onEnd((result) => { + result.errors.forEach(({ text, location }) => { + console.error(`✘ [ERROR] ${text}`); + console.error( + ` ${location.file}:${location.line}:${location.column}:`, + ); + }); + console.log("[watch] build finished"); + }); + }, +}; + +async function main() { + const ctx = await esbuild.context({ + entryPoints: ["src/extension.ts"], + bundle: true, + format: "cjs", + minify: production, + sourcemap: !production, + sourcesContent: false, + platform: "node", + outfile: "dist/extension.js", + external: ["vscode", "web-tree-sitter"], + logLevel: "silent", + plugins: [ + /* add to the end of plugins array */ + esbuildProblemMatcherPlugin, + ], + }); + if (watch) { + await ctx.watch(); + } else { + await ctx.rebuild(); + await ctx.dispose(); + } +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/extensions/vscode/eslint.config.mjs b/extensions/vscode/eslint.config.mjs new file mode 100644 index 00000000..e1c8ab1b --- /dev/null +++ b/extensions/vscode/eslint.config.mjs @@ -0,0 +1,33 @@ +import typescriptEslint from "typescript-eslint"; + +export default [ + { + files: ["**/*.ts"], + }, + { + plugins: { + "@typescript-eslint": typescriptEslint.plugin, + }, + + languageOptions: { + parser: typescriptEslint.parser, + ecmaVersion: 2022, + sourceType: "module", + }, + + rules: { + "@typescript-eslint/naming-convention": [ + "warn", + { + selector: "import", + format: ["camelCase", "PascalCase"], + }, + ], + + curly: "warn", + eqeqeq: "warn", + "no-throw-literal": "warn", + semi: "warn", + }, + }, +]; diff --git a/extensions/vscode/language-configuration.json b/extensions/vscode/language-configuration.json new file mode 100644 index 00000000..296e85ad --- /dev/null +++ b/extensions/vscode/language-configuration.json @@ -0,0 +1,19 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "\"", "close": "\"" }, + { "open": "'", "close": "'" }, + { "open": "/*", "close": "*/" } + ] +} diff --git a/extensions/vscode/package-lock.json b/extensions/vscode/package-lock.json new file mode 100644 index 00000000..9f15d090 --- /dev/null +++ b/extensions/vscode/package-lock.json @@ -0,0 +1,8911 @@ +{ + "name": "silverscript", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "silverscript", + "version": "0.1.0", + "dependencies": { + "vscode-languageclient": "9.0.1", + "web-tree-sitter": "0.26.3" + }, + "devDependencies": { + "@types/mocha": "10.0.10", + "@types/node": "22.x", + "@types/vscode": "1.108.1", + "@vscode/test-cli": "0.0.12", + "@vscode/test-electron": "2.5.2", + "@vscode/vsce": "^3.7.1", + "esbuild": "0.27.2", + "eslint": "9.39.2", + "npm-run-all": "4.1.5", + "typescript": "5.9.3", + "typescript-eslint": "8.52.0" + }, + "engines": { + "vscode": "^1.108.0" + } + }, + "node_modules/@azu/format-text": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.2.tgz", + "integrity": "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@azu/style-format": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.1.tgz", + "integrity": "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "@azu/format-text": "^1.0.1" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", + "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz", + "integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.0.tgz", + "integrity": "sha512-uWC0fssc+hs1TGGVkkghiaFkkS7NkTxfnCH+Hdg+yTehTpMcehpok4PgUKKdyCH+9ldu6FhiHRv84Ntqj1vVcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^4.2.0", + "@azure/msal-node": "^3.5.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.28.2.tgz", + "integrity": "sha512-6vYUMvs6kJxJgxaCmHn/F8VxjLHNh7i9wzfwPGf8kyBJ8Gg2yvBXx175Uev8LdrD1F5C4o7qHa2CC4IrhGE1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "15.14.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "15.14.2", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.14.2.tgz", + "integrity": "sha512-n8RBJEUmd5QotoqbZfd+eGBkzuFI1KX6jw2b3WcpSyGjwmzoeI/Jb99opIBPHpb8y312NB+B6+FGi2ZVSR8yfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.8.7.tgz", + "integrity": "sha512-a+Xnrae+uwLnlw68bplS1X4kuJ9F/7K6afuMFyRkNIskhjgDezl5Fhrx+1pmAlDmC0VaaAxjRQMp1OmcqVwkIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "15.14.2", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@secretlint/config-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz", + "integrity": "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/config-loader": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/config-loader/-/config-loader-10.2.2.tgz", + "integrity": "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "ajv": "^8.17.1", + "debug": "^4.4.1", + "rc-config-loader": "^4.1.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/config-loader/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@secretlint/config-loader/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/core/-/core-10.2.2.tgz", + "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/formatter/-/formatter-10.2.2.tgz", + "integrity": "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@textlint/linter-formatter": "^15.2.0", + "@textlint/module-interop": "^15.2.0", + "@textlint/types": "^15.2.0", + "chalk": "^5.4.1", + "debug": "^4.4.1", + "pluralize": "^8.0.0", + "strip-ansi": "^7.1.0", + "table": "^6.9.0", + "terminal-link": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/formatter/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@secretlint/node": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/node/-/node-10.2.2.tgz", + "integrity": "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-loader": "^10.2.2", + "@secretlint/core": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "p-map": "^7.0.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/profiler/-/profiler-10.2.2.tgz", + "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/resolver": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/resolver/-/resolver-10.2.2.tgz", + "integrity": "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-formatter-sarif": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", + "integrity": "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-sarif-builder": "^3.2.0" + } + }, + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/types": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/types/-/types-10.2.2.tgz", + "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@textlint/ast-node-types": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.5.1.tgz", + "integrity": "sha512-2ABQSaQoM9u9fycXLJKcCv4XQulJWTUSwjo6F0i/ujjqOH8/AZ2A0RDKKbAddqxDhuabVB20lYoEsZZgzehccg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-15.5.1.tgz", + "integrity": "sha512-7wfzpcQtk7TZ3UJO2deTI71mJCm4VvPGUmSwE4iuH6FoaxpdWpwSBiMLcZtjYrt/oIFOtNz0uf5rI+xJiHTFww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azu/format-text": "^1.0.2", + "@azu/style-format": "^1.0.1", + "@textlint/module-interop": "15.5.1", + "@textlint/resolver": "15.5.1", + "@textlint/types": "15.5.1", + "chalk": "^4.1.2", + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "lodash": "^4.17.21", + "pluralize": "^2.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "table": "^6.9.0", + "text-table": "^0.2.0" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/pluralize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", + "integrity": "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@textlint/module-interop": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-15.5.1.tgz", + "integrity": "sha512-Y1jcFGCKNSmHxwsLO3mshOfLYX4Wavq2+w5BG6x5lGgZv0XrF1xxURRhbnhns4LzCu0fAcx6W+3V8/1bkyTZCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/resolver": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/@textlint/resolver/-/resolver-15.5.1.tgz", + "integrity": "sha512-CVHxMIm8iNGccqM12CQ/ycvh+HjJId4RyC6as5ynCcp2E1Uy1TCe0jBWOpmLsbT4Nx15Ke29BmspyByawuIRyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/types": { + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/@textlint/types/-/types-15.5.1.tgz", + "integrity": "sha512-IY1OVZZk8LOOrbapYCsaeH7XSJT89HVukixDT8CoiWMrKGCTCZ3/Kzoa3DtMMbY8jtY777QmPOVCNnR+8fF6YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@textlint/ast-node-types": "15.5.1" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sarif": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.7.tgz", + "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.108.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.108.1.tgz", + "integrity": "sha512-DerV0BbSzt87TbrqmZ7lRDIYaMiqvP8tmJTzW2p49ZBVtGUnGAu2RGQd1Wv4XMzEVUpaHbsemVM5nfuQJj7H6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz", + "integrity": "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/type-utils": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.52.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.52.0.tgz", + "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.52.0", + "@typescript-eslint/types": "^8.52.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz", + "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz", + "integrity": "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.52.0.tgz", + "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.52.0", + "@typescript-eslint/tsconfig-utils": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.52.0.tgz", + "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.52.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.3.tgz", + "integrity": "sha512-91fp6CAAJSRtH5ja95T1FHSKa8aPW9/Zw6cta81jlZTUw/+Vq8jM/AfF/14h2b71wwR84JUTW/3Y8QPhDAawFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.12.tgz", + "integrity": "sha512-iYN0fDg29+a2Xelle/Y56Xvv7Nc8Thzq4VwpzAF/SIE6918rDicqfsQxV6w1ttr2+SOm+10laGuY9FG2ptEKsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mocha": "^10.0.10", + "c8": "^10.1.3", + "chokidar": "^3.6.0", + "enhanced-resolve": "^5.18.3", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^11.7.4", + "supports-color": "^10.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", + "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^8.1.0", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vscode/vsce": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.7.1.tgz", + "integrity": "sha512-OTm2XdMt2YkpSn2Nx7z2EJtSuhRHsTPYsSK59hr3v8jRArK+2UEoju4Jumn1CmpgoBLGI6ReHLJ/czYltNUW3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@secretlint/node": "^10.1.2", + "@secretlint/secretlint-formatter-sarif": "^10.1.2", + "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", + "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^12.1.0", + "form-data": "^4.0.0", + "glob": "^11.0.0", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^14.1.0", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "secretlint": "^10.1.2", + "semver": "^7.5.2", + "tmp": "^0.2.3", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce/node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@vscode/vsce/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@vscode/vsce/node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/glob/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@vscode/vsce/node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz", + "integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vscode/vsce/node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vscode/vsce/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@vscode/vsce/node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", + "integrity": "sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.1", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^7.0.1", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "monocart-coverage-reports": "^2" + }, + "peerDependenciesMeta": { + "monocart-coverage-reports": { + "optional": true + } + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/globby/node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/mocha/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-sarif-builder": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", + "integrity": "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc-config-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.3.tgz", + "integrity": "sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "js-yaml": "^4.1.0", + "json5": "^2.2.2", + "require-from-string": "^2.0.2" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/secretlint/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/secretlint/node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/secretlint/node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/secretlint/node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/secretlint/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.52.0.tgz", + "integrity": "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.52.0", + "@typescript-eslint/parser": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", + "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/web-tree-sitter": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.26.3.tgz", + "integrity": "sha512-JIVgIKFS1w6lejxSntCtsS/QsE/ecTS00en809cMxMPxaor6MvUnQ+ovG8uTTTvQCFosSh4MeDdI5bSGw5SoBw==", + "license": "MIT" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/extensions/vscode/package.json b/extensions/vscode/package.json new file mode 100644 index 00000000..96ea69fe --- /dev/null +++ b/extensions/vscode/package.json @@ -0,0 +1,97 @@ +{ + "name": "silverscript", + "publisher": "IzioDev", + "displayName": "SilverScript", + "description": "Kaspa SilverScript", + "version": "0.1.3", + "repository": { + "url": "https://github.com/kaspanet/silverscript", + "directory": "extensions/vscode" + }, + "license": "ISC", + "author": { + "name": "Kaspa Developers" + }, + "engines": { + "vscode": "^1.108.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onLanguage:silverscript" + ], + "main": "./dist/extension.js", + "contributes": { + "languages": [ + { + "id": "silverscript", + "aliases": [ + "SilverScript", + "silverscript" + ], + "extensions": [ + ".sil" + ], + "configuration": "./language-configuration.json" + } + ], + "configuration": { + "type": "object", + "title": "SilverScript", + "properties": { + "silverscript.covenantsEnabled": { + "type": "boolean", + "default": true, + "description": "Enable covenants-only opcodes." + }, + "silverscript.withoutSelector": { + "type": "boolean", + "default": false, + "description": "Compile without function selector (single entrypoint)." + }, + "silverscript.maxDiagnostics": { + "type": "number", + "default": 200, + "description": "Maximum diagnostics to report per document." + }, + "silverscript.enableSemanticTokens": { + "type": "boolean", + "default": true, + "description": "Enable semantic tokens from the LSP." + } + } + } + }, + "scripts": { + "vscode:prepublish": "npm run package", + "compile": "npm run check-types && npm run lint && node esbuild.js", + "watch": "npm-run-all -p watch:*", + "watch:esbuild": "node esbuild.js --watch", + "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", + "package": "npm run check-types && npm run lint && node esbuild.js --production", + "compile-tests": "tsc -p . --outDir out", + "watch-tests": "tsc -p . -w --outDir out", + "pretest": "npm run compile-tests && npm run compile && npm run lint", + "check-types": "tsc --noEmit", + "lint": "eslint src", + "test": "vscode-test" + }, + "devDependencies": { + "@types/mocha": "10.0.10", + "@types/node": "22.x", + "@types/vscode": "1.108.1", + "@vscode/test-cli": "0.0.12", + "@vscode/test-electron": "2.5.2", + "@vscode/vsce": "^3.7.1", + "esbuild": "0.27.2", + "eslint": "9.39.2", + "npm-run-all": "4.1.5", + "typescript": "5.9.3", + "typescript-eslint": "8.52.0" + }, + "dependencies": { + "vscode-languageclient": "9.0.1", + "web-tree-sitter": "0.26.3" + } +} diff --git a/extensions/vscode/queries/highlights.scm b/extensions/vscode/queries/highlights.scm new file mode 100644 index 00000000..d730b378 --- /dev/null +++ b/extensions/vscode/queries/highlights.scm @@ -0,0 +1,126 @@ +(comment) @comment + +(string_literal) @string + +(number_literal) @number + +(hex_literal) @number + +(boolean_literal) @boolean + +(date_literal) @function.builtin + +(type_name) @type + +(instantiation + (identifier) @type.builtin + (#match? @type.builtin + "^(LockingBytecodeNullData|ScriptPubKeyP2PK|ScriptPubKeyP2SH|ScriptPubKeyP2SHFromRedeemScript)$")) + +(instantiation + (identifier) @type) + +(contract_definition + name: (identifier) @type) + +(function_definition + name: (identifier) @function) + +(constant_definition + name: (identifier) @constant) + +(contract_field_definition + name: (identifier) @property) + +(variable_definition + name: (identifier) @variable) + +(parameter + (identifier) @variable.parameter) + +(tx_var) @variable.builtin + +(nullary_op) @variable.builtin + +(output_root) @variable.builtin + +(input_root) @variable.builtin + +(tuple_index + "[" @operator + "]" @operator) + +(output_field + "." @operator) + +(input_field + "." @operator) + +(output_field_name) @property + +(input_field_name) @property + +(state_entry + (identifier) @property) + +(state_typed_binding + (identifier) @property + ":" + (type_name) + (identifier) @variable) + +(function_call + (identifier) @function.builtin + (#match? @function.builtin + "^(readInputState|validateOutputState|verifyOutputState|verifyOutputStates|OpSha256|sha256|OpTxSubnetId|OpTxGas|OpTxPayloadLen|OpTxPayloadSubstr|OpOutpointTxId|OpOutpointIndex|OpTxInputScriptSigLen|OpTxInputScriptSigSubstr|OpTxInputSeq|OpTxInputIsCoinbase|OpTxInputSpkLen|OpTxInputSpkSubstr|OpTxOutputSpkLen|OpTxOutputSpkSubstr|OpAuthOutputCount|OpAuthOutputIdx|OpInputCovenantId|OpCovInputCount|OpCovInputIdx|OpCovOutCount|OpCovOutputIdx|OpNum2Bin|OpBin2Num|OpChainblockSeqCommit|checkDataSig|checkSig|checkMultiSig|blake2b)$")) + +(unary_suffix) @property + +(split_call + ".split" @function.method) + +(slice_call + ".slice" @function.method) + +(reverse_call + ".reverse" @function.method) + +(array_bound) @number + +[ + "pragma" + "silverscript" + "contract" + "entrypoint" + "function" + "constant" + "if" + "else" + "for" + "new" + "require" + "return" + "yield" + "console.log" +] @keyword + +[ + "||" + "&&" + "==" + "!=" + "<" + "<=" + ">" + ">=" + "+" + "-" + "*" + "/" + "%" + "!" + "&" + "|" + "^" + "=" +] @operator diff --git a/extensions/vscode/src/extension.ts b/extensions/vscode/src/extension.ts new file mode 100644 index 00000000..a82a576c --- /dev/null +++ b/extensions/vscode/src/extension.ts @@ -0,0 +1,397 @@ +import * as vscode from "vscode"; +import * as path from "path"; +import * as fs from "fs/promises"; +import { Language, Parser, Query } from "web-tree-sitter"; +import type { QueryCapture } from "web-tree-sitter"; + +const TOKEN_TYPES = [ + "comment", + "string", + "number", + "keyword", + "operator", + "function", + "constant", + "variable", + "type", + "property", + "parameter", + "boolean", +] as const; + +const TOKEN_MODIFIERS = ["defaultLibrary"] as const; + +const legend = new vscode.SemanticTokensLegend( + [...TOKEN_TYPES], + [...TOKEN_MODIFIERS], +); + +const LOG_DEBUG = true; +let outputChannel: vscode.OutputChannel | null = null; + +function logInfo(message: string) { + if (!outputChannel) { + return; + } + outputChannel.appendLine(`[${new Date().toISOString()}] ${message}`); +} + +function logDebug(message: string) { + if (!LOG_DEBUG) { + return; + } + logInfo(message); +} + +function logError(message: string, error: unknown) { + const err = + error instanceof Error + ? `${error.message}\n${error.stack ?? ""}` + : String(error); + logInfo(`${message}\n${err}`); +} + +type TokenType = (typeof TOKEN_TYPES)[number]; +type TokenModifier = (typeof TOKEN_MODIFIERS)[number]; + +const TOKEN_TYPE_TO_INDEX = new Map( + TOKEN_TYPES.map((token, index) => [token, index]), +); +const TOKEN_MODIFIER_TO_MASK = new Map( + TOKEN_MODIFIERS.map((modifier, index) => [modifier, 1 << index]), +); + +function mapCaptureToToken(captureName: string): { + type: TokenType | null; + modifiers: TokenModifier[]; +} { + const parts = captureName.split("."); + const base = parts[0]; + const mods = new Set(); + + if (parts.includes("builtin")) { + mods.add("defaultLibrary"); + } + + switch (base) { + case "comment": + return { type: "comment", modifiers: [...mods] }; + case "string": + return { type: "string", modifiers: [...mods] }; + case "number": + return { type: "number", modifiers: [...mods] }; + case "boolean": + return { type: "boolean", modifiers: [...mods] }; + case "keyword": + return { type: "keyword", modifiers: [...mods] }; + case "operator": + return { type: "operator", modifiers: [...mods] }; + case "function": + return { type: "function", modifiers: [...mods] }; + case "constant": + return { type: "constant", modifiers: [...mods] }; + case "type": + return { type: "type", modifiers: [...mods] }; + case "property": + return { type: "property", modifiers: [...mods] }; + case "variable": + if (parts.includes("parameter")) { + return { type: "parameter", modifiers: [...mods] }; + } + return { type: "variable", modifiers: [...mods] }; + default: + return { type: null, modifiers: [] }; + } +} + +function tokenTypeIndex(t: TokenType) { + return TOKEN_TYPE_TO_INDEX.get(t); +} + +function tokenModifierMask(mods: readonly TokenModifier[]) { + let mask = 0; + for (const m of mods) { + const bit = TOKEN_MODIFIER_TO_MASK.get(m); + if (bit !== undefined) { + mask |= bit; + } + } + return mask; +} + +let initPromise: Promise | null = null; +let cachedLanguage: Language | null = null; +let cachedQuery: Query | null = null; + +async function initTreeSitter(context: vscode.ExtensionContext) { + if (initPromise) { + return initPromise; + } + + initPromise = (async () => { + try { + const runtimeWasmPath = context.asAbsolutePath( + path.join("node_modules", "web-tree-sitter", "web-tree-sitter.wasm"), + ); + logDebug(`runtime wasm: ${runtimeWasmPath}`); + + // web-tree-sitter needs its runtime wasm (tree-sitter.wasm). Provide it via locateFile. + await Parser.init({ + locateFile: (scriptName?: string) => { + const resolved = scriptName + ? context.asAbsolutePath( + path.join("node_modules", "web-tree-sitter", scriptName), + ) + : runtimeWasmPath; + logDebug(`locateFile(${scriptName ?? "undefined"}): ${resolved}`); + return resolved; + }, + }); + + const parserWasmPath = context.asAbsolutePath( + path.join("assets", "tree-sitter-silverscript.wasm"), + ); + logDebug(`language wasm: ${parserWasmPath}`); + cachedLanguage = await Language.load(parserWasmPath); + + const highlightsPath = context.asAbsolutePath( + path.join("queries", "highlights.scm"), + ); + logDebug(`highlights: ${highlightsPath}`); + const highlightsSource = await fs.readFile(highlightsPath, "utf8"); + cachedQuery = new Query(cachedLanguage, highlightsSource); + } catch (error) { + logError("Tree-sitter init failed.", error); + initPromise = null; + throw error; + } + })(); + + return initPromise; +} + +function compareCaptures(a: QueryCapture, b: QueryCapture) { + const ap = a.node.startPosition; + const bp = b.node.startPosition; + if (ap.row !== bp.row) { + return ap.row - bp.row; + } + if (ap.column !== bp.column) { + return ap.column - bp.column; + } + // stable tie-break + const ae = a.node.endPosition; + const be = b.node.endPosition; + if (ae.row !== be.row) { + return ae.row - be.row; + } + return ae.column - be.column; +} + +function splitMultiLineToken( + document: vscode.TextDocument, + start: vscode.Position, + end: vscode.Position, +) { + const ranges: vscode.Range[] = []; + if (start.line === end.line) { + ranges.push(new vscode.Range(start, end)); + return ranges; + } + + // start line segment + const startLineLen = document.lineAt(start.line).text.length; + ranges.push( + new vscode.Range(start, new vscode.Position(start.line, startLineLen)), + ); + + // middle full lines + for (let line = start.line + 1; line < end.line; line++) { + const len = document.lineAt(line).text.length; + if (len > 0) { + ranges.push( + new vscode.Range( + new vscode.Position(line, 0), + new vscode.Position(line, len), + ), + ); + } + } + + // end line segment + if (end.character > 0) { + ranges.push(new vscode.Range(new vscode.Position(end.line, 0), end)); + } + + return ranges; +} + +class SilverScriptSemanticTokensProvider + implements vscode.DocumentSemanticTokensProvider +{ + private _onDidChange = new vscode.EventEmitter(); + onDidChangeSemanticTokens = this._onDidChange.event; + + public triggerRefresh() { + this._onDidChange.fire(); + } + + async provideDocumentSemanticTokens( + document: vscode.TextDocument, + _cancellationToken: vscode.CancellationToken, + ): Promise { + logDebug( + `semantic tokens request: ${document.uri.toString()} (${document.languageId})`, + ); + + try { + await initTreeSitter(this.context); + } catch (error) { + logError("Tree-sitter init error during tokenization.", error); + return new vscode.SemanticTokens(new Uint32Array()); + } + + const language = cachedLanguage; + const query = cachedQuery; + + if (!language || !query) { + logInfo("Tree-sitter language/query not initialized."); + return new vscode.SemanticTokens(new Uint32Array()); + } + + const parser = new Parser(); + parser.setLanguage(language); + + const text = document.getText(); + const tree = parser.parse(text); + if (!tree) { + parser.delete(); + return new vscode.SemanticTokens(new Uint32Array()); + } + + try { + const captures: QueryCapture[] = query.captures(tree.rootNode); + logDebug(`captures: ${captures.length}`); + captures.sort(compareCaptures); + + const priority = (name: string) => { + if (name.startsWith("function")) { + return 100; + } + if (name.startsWith("type")) { + return 90; + } + if (name.startsWith("keyword")) { + return 80; + } + if (name.startsWith("string")) { + return 70; + } + if (name.startsWith("number") || name.startsWith("boolean")) { + return 70; + } + if (name.startsWith("comment")) { + return 60; + } + if (name.startsWith("operator")) { + return 50; + } + if (name.startsWith("property")) { + return 40; + } + if (name.startsWith("constant")) { + return 35; + } + if (name.startsWith("variable")) { + return 30; + } + return 0; + }; + + const bestByRange = new Map(); + for (const capture of captures) { + const sp = capture.node.startPosition; + const ep = capture.node.endPosition; + const key = `${sp.row}:${sp.column}-${ep.row}:${ep.column}`; + const existing = bestByRange.get(key); + if (!existing || priority(capture.name) > priority(existing.name)) { + bestByRange.set(key, capture); + } + } + + const finalCaps = [...bestByRange.values()].sort(compareCaptures); + const builder = new vscode.SemanticTokensBuilder(legend); + + for (const cap of finalCaps) { + const mapped = mapCaptureToToken(cap.name); + if (!mapped.type) { + continue; + } + + const typeIndex = tokenTypeIndex(mapped.type); + if (typeIndex === undefined) { + continue; + } + + const sp = cap.node.startPosition; + const ep = cap.node.endPosition; + + const start = new vscode.Position(sp.row, sp.column); + const end = new vscode.Position(ep.row, ep.column); + + for (const range of splitMultiLineToken(document, start, end)) { + const length = range.end.character - range.start.character; + if (length <= 0) { + continue; + } + + builder.push( + range.start.line, + range.start.character, + length, + typeIndex, + tokenModifierMask(mapped.modifiers), + ); + } + } + + return builder.build(); + } finally { + tree.delete(); + parser.delete(); + } + } + + constructor(private readonly context: vscode.ExtensionContext) {} +} + +export function activate(context: vscode.ExtensionContext) { + outputChannel = vscode.window.createOutputChannel("SilverScript"); + context.subscriptions.push(outputChannel); + logInfo("SilverScript extension activated."); + + // TODO: add LSP (LanguageClient + LanguageServer) + + const provider = new SilverScriptSemanticTokensProvider(context); + + context.subscriptions.push( + vscode.languages.registerDocumentSemanticTokensProvider( + { language: "silverscript" }, + provider, + legend, + ), + ); + + context.subscriptions.push( + vscode.workspace.onDidChangeTextDocument((e) => { + if (e.document.languageId === "silverscript") { + provider.triggerRefresh(); + } + }), + ); +} + +// TODO: deactivate LSP +export function deactivate() { + return undefined; +} diff --git a/extensions/vscode/tsconfig.json b/extensions/vscode/tsconfig.json new file mode 100644 index 00000000..5f1f6ad9 --- /dev/null +++ b/extensions/vscode/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "lib": ["ES2022"], + "sourceMap": true, + "rootDir": "src", + "strict": true, + "skipLibCheck": true, + }, +} diff --git a/extensions/zed/.gitignore b/extensions/zed/.gitignore new file mode 100644 index 00000000..84cbee6b --- /dev/null +++ b/extensions/zed/.gitignore @@ -0,0 +1 @@ +grammars diff --git a/extensions/zed/README.md b/extensions/zed/README.md new file mode 100644 index 00000000..856c557a --- /dev/null +++ b/extensions/zed/README.md @@ -0,0 +1,24 @@ +### Development + +- Set `repository` in `extensions\zed\extension.toml` to this repository root (absolute path required). +- In Zed, press `Ctrl+Shift+P` and run `install dev extension`, then pick `extensions/zed`. + +#### Live Grammar Changes + +Build the grammar from your working tree and copy the wasm into the dev extension: + +```bash +cd tree-sitter +npm run build:zed +``` + +Then in Zed run `zed: reload extensions`. + +### Release + +Before sharing or committing extension metadata updates, set `rev` to a real commit SHA in +`extensions\zed\extension.toml`. + +### Syntax highlight (`highlights.scm`) + +https://tree-sitter.github.io/tree-sitter/3-syntax-highlighting.html diff --git a/extensions/zed/extension.toml b/extensions/zed/extension.toml new file mode 100644 index 00000000..d020f273 --- /dev/null +++ b/extensions/zed/extension.toml @@ -0,0 +1,19 @@ +id = "silverscript" +name = "SilverScript" +version = "0.1.0" +schema_version = 1 +description = "SilverScript language support." + +languages = ["languages/silverscript"] + +[grammars.silverscript] +# useful for development +# repository = "file:///D:/Dev/kaspa/silverscript" + +repository = "https://github.com/rusty-kaspa/silverscript" +# @TODO(izio): bump after squash merge +rev = "8064ce2fd8588e4fca4499dad0669b80ea5b4165" +path = "tree-sitter" + +[language_servers.silverscript-lsp] +command = "silverscript-lsp" diff --git a/extensions/zed/languages/silverscript/config.toml b/extensions/zed/languages/silverscript/config.toml new file mode 100644 index 00000000..88d2802b --- /dev/null +++ b/extensions/zed/languages/silverscript/config.toml @@ -0,0 +1,17 @@ +name = "SilverScript" +grammar = "silverscript" +path_suffixes = ["sil"] +# language_servers = ["silverscript-lsp"] + +line_comments = ["// "] +block_comment = { start = "/*", prefix = "* ", end = "*/", tab_size = 1 } + +autoclose_before = ";:.,=}])" +brackets = [ + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string"] }, + { start = "/*", end = "*/", close = true, newline = false, not_in = ["string", "comment"] }, +] diff --git a/extensions/zed/languages/silverscript/highlights.scm b/extensions/zed/languages/silverscript/highlights.scm new file mode 100644 index 00000000..d730b378 --- /dev/null +++ b/extensions/zed/languages/silverscript/highlights.scm @@ -0,0 +1,126 @@ +(comment) @comment + +(string_literal) @string + +(number_literal) @number + +(hex_literal) @number + +(boolean_literal) @boolean + +(date_literal) @function.builtin + +(type_name) @type + +(instantiation + (identifier) @type.builtin + (#match? @type.builtin + "^(LockingBytecodeNullData|ScriptPubKeyP2PK|ScriptPubKeyP2SH|ScriptPubKeyP2SHFromRedeemScript)$")) + +(instantiation + (identifier) @type) + +(contract_definition + name: (identifier) @type) + +(function_definition + name: (identifier) @function) + +(constant_definition + name: (identifier) @constant) + +(contract_field_definition + name: (identifier) @property) + +(variable_definition + name: (identifier) @variable) + +(parameter + (identifier) @variable.parameter) + +(tx_var) @variable.builtin + +(nullary_op) @variable.builtin + +(output_root) @variable.builtin + +(input_root) @variable.builtin + +(tuple_index + "[" @operator + "]" @operator) + +(output_field + "." @operator) + +(input_field + "." @operator) + +(output_field_name) @property + +(input_field_name) @property + +(state_entry + (identifier) @property) + +(state_typed_binding + (identifier) @property + ":" + (type_name) + (identifier) @variable) + +(function_call + (identifier) @function.builtin + (#match? @function.builtin + "^(readInputState|validateOutputState|verifyOutputState|verifyOutputStates|OpSha256|sha256|OpTxSubnetId|OpTxGas|OpTxPayloadLen|OpTxPayloadSubstr|OpOutpointTxId|OpOutpointIndex|OpTxInputScriptSigLen|OpTxInputScriptSigSubstr|OpTxInputSeq|OpTxInputIsCoinbase|OpTxInputSpkLen|OpTxInputSpkSubstr|OpTxOutputSpkLen|OpTxOutputSpkSubstr|OpAuthOutputCount|OpAuthOutputIdx|OpInputCovenantId|OpCovInputCount|OpCovInputIdx|OpCovOutCount|OpCovOutputIdx|OpNum2Bin|OpBin2Num|OpChainblockSeqCommit|checkDataSig|checkSig|checkMultiSig|blake2b)$")) + +(unary_suffix) @property + +(split_call + ".split" @function.method) + +(slice_call + ".slice" @function.method) + +(reverse_call + ".reverse" @function.method) + +(array_bound) @number + +[ + "pragma" + "silverscript" + "contract" + "entrypoint" + "function" + "constant" + "if" + "else" + "for" + "new" + "require" + "return" + "yield" + "console.log" +] @keyword + +[ + "||" + "&&" + "==" + "!=" + "<" + "<=" + ">" + ">=" + "+" + "-" + "*" + "/" + "%" + "!" + "&" + "|" + "^" + "=" +] @operator diff --git a/extensions/zed/languages/silverscript/indents.scm b/extensions/zed/languages/silverscript/indents.scm new file mode 100644 index 00000000..cbd39bb3 --- /dev/null +++ b/extensions/zed/languages/silverscript/indents.scm @@ -0,0 +1,8 @@ +(_ "{" "}" @end) @indent +(_ "(" ")" @end) @indent +(_ "[" "]" @end) @indent + +(contract_definition) @indent +(function_definition) @indent +(if_statement) @indent +(for_statement) @indent diff --git a/silverscript-lang/Cargo.toml b/silverscript-lang/Cargo.toml index 4f944ee5..ea4a7210 100644 --- a/silverscript-lang/Cargo.toml +++ b/silverscript-lang/Cargo.toml @@ -24,6 +24,7 @@ secp256k1.workspace = true thiserror.workspace = true serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +clap = { version = "4.5.60", features = ["derive"] } [dev-dependencies] kaspa-addresses.workspace = true diff --git a/silverscript-lang/src/ast.rs b/silverscript-lang/src/ast.rs index 05140b93..d3768eb2 100644 --- a/silverscript-lang/src/ast.rs +++ b/silverscript-lang/src/ast.rs @@ -1,52 +1,96 @@ -use std::collections::HashMap; +use std::fmt; -use pest::Parser; +use chrono::NaiveDateTime; use pest::iterators::Pair; use serde::{Deserialize, Serialize}; -use crate::compiler::CompilerError; -use crate::parser::{Rule, SilverScriptParser}; -use chrono::NaiveDateTime; +use crate::errors::CompilerError; +use crate::parser::{Rule, parse_source_file, parse_type_name as parse_type_name_rule}; +pub use crate::span::{Span, SpanUtils}; + +#[derive(Debug, Clone)] +struct Identifier<'i> { + name: String, + span: Span<'i>, +} #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ContractAst { +pub struct ContractAst<'i> { pub name: String, - pub params: Vec, + pub params: Vec>, #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub fields: Vec, - pub constants: HashMap, - pub functions: Vec, + pub fields: Vec>, + pub constants: Vec>, + pub functions: Vec>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, +} + +impl<'i> fmt::Display for ContractAst<'i> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let pretty = serde_json::to_string_pretty(self).map_err(|_| fmt::Error)?; + f.write_str(&pretty) + } } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ContractFieldAst { +pub struct ContractFieldAst<'i> { pub type_ref: TypeRef, pub name: String, - pub expr: Expr, + pub expr: Expr<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FunctionAst { +pub struct FunctionAst<'i> { pub name: String, - pub params: Vec, - #[serde(default)] + pub params: Vec>, pub entrypoint: bool, #[serde(default)] pub return_types: Vec, - pub body: Vec, + pub body: Vec>, + #[serde(skip_deserializing)] + pub return_type_spans: Vec>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, + #[serde(skip_deserializing)] + pub body_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ParamAst { +pub struct ParamAst<'i> { pub type_ref: TypeRef, pub name: String, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StateBindingAst { +pub struct StateBindingAst<'i> { pub field_name: String, pub type_ref: TypeRef, pub name: String, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub field_span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -123,28 +167,166 @@ impl TypeRef { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", content = "data", rename_all = "snake_case")] -pub enum Statement { - VariableDefinition { type_ref: TypeRef, modifiers: Vec, name: String, expr: Option }, - TupleAssignment { left_type_ref: TypeRef, left_name: String, right_type_ref: TypeRef, right_name: String, expr: Expr }, - ArrayPush { name: String, expr: Expr }, - FunctionCall { name: String, args: Vec }, - FunctionCallAssign { bindings: Vec, name: String, args: Vec }, - StateFunctionCallAssign { bindings: Vec, name: String, args: Vec }, - Assign { name: String, expr: Expr }, - TimeOp { tx_var: TimeVar, expr: Expr, message: Option }, - Require { expr: Expr, message: Option }, - If { condition: Expr, then_branch: Vec, else_branch: Option> }, - For { ident: String, start: Expr, end: Expr, body: Vec }, - Yield { expr: Expr }, - Return { exprs: Vec }, - Console { args: Vec }, +pub enum Statement<'i> { + VariableDefinition { + type_ref: TypeRef, + #[serde(default)] + modifiers: Vec, + name: String, + expr: Option>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + type_span: Span<'i>, + #[serde(skip_deserializing)] + modifier_spans: Vec>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + TupleAssignment { + left_type_ref: TypeRef, + left_name: String, + right_type_ref: TypeRef, + right_name: String, + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + left_type_span: Span<'i>, + #[serde(skip_deserializing)] + left_name_span: Span<'i>, + #[serde(skip_deserializing)] + right_type_span: Span<'i>, + #[serde(skip_deserializing)] + right_name_span: Span<'i>, + }, + ArrayPush { + name: String, + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + FunctionCall { + name: String, + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + FunctionCallAssign { + bindings: Vec>, + name: String, + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + StateFunctionCallAssign { + bindings: Vec>, + name: String, + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + Assign { + name: String, + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + TimeOp { + tx_var: TimeVar, + expr: Expr<'i>, + message: Option, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + tx_var_span: Span<'i>, + #[serde(skip_deserializing)] + message_span: Option>, + }, + Require { + expr: Expr<'i>, + message: Option, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + message_span: Option>, + }, + If { + condition: Expr<'i>, + then_branch: Vec>, + else_branch: Option>>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + then_span: Span<'i>, + #[serde(skip_deserializing)] + else_span: Option>, + }, + For { + ident: String, + start: Expr<'i>, + end: Expr<'i>, + body: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + #[serde(skip_deserializing)] + ident_span: Span<'i>, + #[serde(skip_deserializing)] + body_span: Span<'i>, + }, + Yield { + expr: Expr<'i>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + Return { + exprs: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + Console { + args: Vec>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, +} + +impl<'i> Statement<'i> { + pub fn span(&self) -> Span<'i> { + match self { + Statement::VariableDefinition { span, .. } + | Statement::TupleAssignment { span, .. } + | Statement::ArrayPush { span, .. } + | Statement::FunctionCall { span, .. } + | Statement::FunctionCallAssign { span, .. } + | Statement::StateFunctionCallAssign { span, .. } + | Statement::Assign { span, .. } + | Statement::Return { span, .. } + | Statement::TimeOp { span, .. } + | Statement::Require { span, .. } + | Statement::If { span, .. } + | Statement::For { span, .. } + | Statement::Yield { span, .. } + | Statement::Console { span, .. } => *span, + } + } } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", content = "data", rename_all = "snake_case")] -pub enum ConsoleArg { - Identifier(String), - Literal(Expr), +pub enum ConsoleArg<'i> { + Identifier(String, #[serde(skip_deserializing)] Span<'i>), + Literal(Expr<'i>), } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -154,85 +336,200 @@ pub enum TimeVar { TxTime, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -#[serde(tag = "kind", content = "data", rename_all = "snake_case")] -pub enum Expr { - Int(i64), - Bool(bool), - Byte(u8), - String(String), - Identifier(String), - Array(Vec), - Call { name: String, args: Vec }, - New { name: String, args: Vec }, - Split { source: Box, index: Box, part: SplitPart }, - Slice { source: Box, start: Box, end: Box }, - ArrayIndex { source: Box, index: Box }, - Unary { op: UnaryOp, expr: Box }, - Binary { op: BinaryOp, left: Box, right: Box }, - IfElse { condition: Box, then_expr: Box, else_expr: Box }, - Nullary(NullaryOp), - Introspection { kind: IntrospectionKind, index: Box }, - StateObject(Vec), +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Expr<'i> { + // TODO: evaluate splitting kind in two: + // - actual Expressions + // - user defined primitive Values + #[serde(flatten)] + pub kind: ExprKind<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct StateFieldExpr { - pub name: String, - pub expr: Expr, +impl<'i> Expr<'i> { + pub fn new(kind: ExprKind<'i>, span: Span<'i>) -> Self { + Self { kind, span } + } + + pub fn int(value: i64) -> Self { + Self::new(ExprKind::Int(value), Span::default()) + } + + pub fn bool(value: bool) -> Self { + Self::new(ExprKind::Bool(value), Span::default()) + } + + pub fn byte(value: u8) -> Self { + Self::new(ExprKind::Byte(value), Span::default()) + } + + pub fn bytes(value: Vec) -> Self { + Self::new(ExprKind::Array(value.into_iter().map(Expr::byte).collect()), Span::default()) + } + + pub fn string(value: impl Into) -> Self { + Self::new(ExprKind::String(value.into()), Span::default()) + } + + pub fn identifier(value: impl Into) -> Self { + Self::new(ExprKind::Identifier(value.into()), Span::default()) + } + + pub fn call(name: impl Into, args: Vec>) -> Self { + Self::new(ExprKind::Call { name: name.into(), args, name_span: Span::default() }, Span::default()) + } } -impl From for Expr { +impl<'i> From for Expr<'i> { fn from(value: i64) -> Self { - Expr::Int(value) + Expr::int(value) } } -impl From for Expr { +impl<'i> From for Expr<'i> { fn from(value: bool) -> Self { - Expr::Bool(value) + Expr::bool(value) } } -impl From> for Expr { +impl<'i> From> for Expr<'i> { fn from(value: Vec) -> Self { - Expr::Array(value.into_iter().map(Expr::Byte).collect()) + Expr::bytes(value) } } -impl From for Expr { +impl<'i> From for Expr<'i> { fn from(value: String) -> Self { - Expr::String(value) + Expr::string(value) + } +} + +impl<'i> From<&str> for Expr<'i> { + fn from(value: &str) -> Self { + Expr::string(value) } } -impl From> for Expr { - fn from(value: Vec) -> Self { - Expr::Array(value.into_iter().map(Expr::Int).collect()) +impl<'i> From> for Expr<'i> { + fn from(values: Vec) -> Self { + let exprs = values.into_iter().map(Expr::int).collect(); + Expr::new(ExprKind::Array(exprs), Span::default()) } } -impl From>> for Expr { - fn from(value: Vec>) -> Self { - Expr::Array(value.into_iter().map(|bytes| Expr::Array(bytes.into_iter().map(Expr::Byte).collect())).collect()) +impl<'i> From>> for Expr<'i> { + fn from(values: Vec>) -> Self { + Expr::new(ExprKind::Array(values), Span::default()) } } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +impl<'i> From>> for Expr<'i> { + fn from(values: Vec>) -> Self { + let exprs = values.into_iter().map(Expr::bytes).collect(); + Expr::new(ExprKind::Array(exprs), Span::default()) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "kind", content = "data", rename_all = "snake_case")] +pub enum ExprKind<'i> { + Int(i64), + Bool(bool), + Byte(u8), + String(String), + DateLiteral(i64), + Identifier(String), + Array(Vec>), + Call { + name: String, + args: Vec>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + New { + name: String, + args: Vec>, + #[serde(skip_deserializing)] + name_span: Span<'i>, + }, + Split { + source: Box>, + index: Box>, + part: SplitPart, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + Slice { + source: Box>, + start: Box>, + end: Box>, + #[serde(skip_deserializing)] + span: Span<'i>, + }, + ArrayIndex { + source: Box>, + index: Box>, + }, + Unary { + op: UnaryOp, + expr: Box>, + }, + Binary { + op: BinaryOp, + left: Box>, + right: Box>, + }, + IfElse { + condition: Box>, + then_expr: Box>, + else_expr: Box>, + }, + Nullary(NullaryOp), + Introspection { + kind: IntrospectionKind, + index: Box>, + #[serde(skip_deserializing)] + field_span: Span<'i>, + }, + StateObject(Vec>), + NumberWithUnit { + value: i64, + unit: String, + }, + UnarySuffix { + source: Box>, + kind: UnarySuffixKind, + #[serde(skip_deserializing)] + span: Span<'i>, + }, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct StateFieldExpr<'i> { + pub name: String, + pub expr: Expr<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum SplitPart { Left, Right, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum UnaryOp { Not, Neg, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum BinaryOp { Or, @@ -253,7 +550,7 @@ pub enum BinaryOp { Mod, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum NullaryOp { ActiveInputIndex, @@ -266,25 +563,44 @@ pub enum NullaryOp { TxLockTime, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum IntrospectionKind { InputValue, InputScriptPubKey, InputSigScript, + /// TODO: not supported yet + InputOutpointTransactionHash, + /// TODO: not supported yet + InputOutpointIndex, + /// TODO: not supported yet + InputSequenceNumber, OutputValue, OutputScriptPubKey, } -fn validate_user_identifier(name: &str) -> Result<(), CompilerError> { - if name.starts_with("__") { - return Err(CompilerError::Unsupported("identifier cannot start with '__'".to_string())); - } - Ok(()) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ConstantAst<'i> { + pub type_ref: TypeRef, + pub name: String, + pub expr: Expr<'i>, + #[serde(skip_deserializing)] + pub span: Span<'i>, + #[serde(skip_deserializing)] + pub type_span: Span<'i>, + #[serde(skip_deserializing)] + pub name_span: Span<'i>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum UnarySuffixKind { + Reverse, + Length, } pub fn parse_type_ref(type_name: &str) -> Result { - let mut pairs = SilverScriptParser::parse(Rule::type_name, type_name)?; + let mut pairs = parse_type_name_rule(type_name)?; let pair = pairs.next().ok_or_else(|| CompilerError::Unsupported("missing type name".to_string()))?; parse_type_name_pair(pair) } @@ -294,7 +610,7 @@ fn parse_type_name_pair(pair: Pair<'_, Rule>) -> Result return Err(CompilerError::Unsupported("expected type name".to_string())); } - let mut inner = pair.clone().into_inner(); + let mut inner = pair.into_inner(); let base = match inner.next().ok_or_else(|| CompilerError::Unsupported("missing base type".to_string()))?.as_str() { "int" => TypeBase::Int, "bool" => TypeBase::Bool, @@ -320,9 +636,7 @@ fn parse_type_name_pair(pair: Pair<'_, Rule>) -> Result if let Ok(size) = raw.parse::() { ArrayDim::Fixed(size) } else { ArrayDim::Constant(raw.to_string()) } } Rule::Identifier => ArrayDim::Constant(size_pair.as_str().to_string()), - _ => { - return Err(CompilerError::Unsupported("invalid array dimension".to_string())); - } + _ => return Err(CompilerError::Unsupported("invalid array dimension".to_string())), }, }; array_dims.push(dim); @@ -331,8 +645,8 @@ fn parse_type_name_pair(pair: Pair<'_, Rule>) -> Result Ok(TypeRef { base, array_dims }) } -pub fn parse_contract_ast(source: &str) -> Result { - let mut pairs = SilverScriptParser::parse(Rule::source_file, source)?; +pub fn parse_contract_ast<'i>(source: &'i str) -> Result, CompilerError> { + let mut pairs = parse_source_file(source)?; let source_pair = pairs.next().ok_or_else(|| CompilerError::Unsupported("empty source".to_string()))?; let mut contract = None; @@ -345,15 +659,19 @@ pub fn parse_contract_ast(source: &str) -> Result { contract.ok_or_else(|| CompilerError::Unsupported("no contract definition".to_string())) } -fn parse_contract_definition(pair: Pair<'_, Rule>) -> Result { +fn parse_contract_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing contract name".to_string()))?; let params_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing contract parameters".to_string()))?; + + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; let params = parse_typed_parameter_list(params_pair)?; let mut functions = Vec::new(); let mut fields = Vec::new(); - let mut constants: HashMap = HashMap::new(); + let mut constants = Vec::new(); for item_pair in inner { if item_pair.as_rule() != Rule::contract_item { @@ -362,286 +680,354 @@ fn parse_contract_definition(pair: Pair<'_, Rule>) -> Result { - functions.push(parse_function_definition(inner_item)?); - } - Rule::contract_field_definition => { - let mut field_inner = inner_item.into_inner(); - let type_pair = field_inner.next().ok_or_else(|| CompilerError::Unsupported("missing field type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; - let name_pair = field_inner.next().ok_or_else(|| CompilerError::Unsupported("missing field name".to_string()))?; - validate_user_identifier(name_pair.as_str())?; - let expr_pair = - field_inner.next().ok_or_else(|| CompilerError::Unsupported("missing field initializer".to_string()))?; - let expr = parse_expression(expr_pair)?; - fields.push(ContractFieldAst { type_ref, name: name_pair.as_str().to_string(), expr }); - } - Rule::constant_definition => { - let mut const_inner = inner_item.into_inner(); - let _type_name = - const_inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant type".to_string()))?; - let name_pair = - const_inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant name".to_string()))?; - validate_user_identifier(name_pair.as_str())?; - let expr_pair = - const_inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant initializer".to_string()))?; - let expr = parse_expression(expr_pair)?; - constants.insert(name_pair.as_str().to_string(), expr); - } + Rule::function_definition => functions.push(parse_function_definition(inner_item)?), + Rule::contract_field_definition => fields.push(parse_contract_field_definition(inner_item)?), + Rule::constant_definition => constants.push(parse_constant_definition(inner_item)?), _ => {} } } } - Ok(ContractAst { name: name_pair.as_str().to_string(), params, fields, constants, functions }) + Ok(ContractAst { name, params, fields, constants, functions, span, name_span }) } -fn parse_function_definition(pair: Pair<'_, Rule>) -> Result { +fn parse_function_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); - let mut entrypoint = false; - let name_pair = match inner.next() { - Some(pair) if pair.as_rule() == Rule::entrypoint => { - entrypoint = true; - inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))? - } - Some(pair) => pair, - None => return Err(CompilerError::Unsupported("missing function name".to_string())), + + let first = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?; + let (entrypoint, name_pair) = if first.as_rule() == Rule::entrypoint { + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?; + (true, name_pair) + } else { + (false, first) }; + let params_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function parameters".to_string()))?; let params = parse_typed_parameter_list(params_pair)?; + let mut return_types = Vec::new(); + let mut return_type_spans = Vec::new(); if let Some(next) = inner.peek() { if next.as_rule() == Rule::return_type_list { let return_pair = inner.next().expect("checked"); - return_types = parse_return_type_list(return_pair)?; + let (types, spans) = parse_return_type_list(return_pair)?; + return_types = types; + return_type_spans = spans; } } + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + let mut body = Vec::new(); - for stmt in inner { - body.push(parse_statement(stmt)?); + let mut body_span: Option> = None; + for stmt_pair in inner { + let stmt = parse_statement(stmt_pair)?; + let stmt_span = stmt.span(); + body_span = Some(match body_span { + None => stmt_span, + Some(prev) => prev.join(&stmt_span), + }); + body.push(stmt); } + let body_span = body_span.unwrap_or(span); - Ok(FunctionAst { name: name_pair.as_str().to_string(), params, entrypoint, return_types, body }) + Ok(FunctionAst { name, entrypoint, params, return_types, return_type_spans, body, span, name_span, body_span }) } -fn parse_statement(pair: Pair<'_, Rule>) -> Result { +fn parse_constant_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant type".to_string()))?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant name".to_string()))?; + let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constant initializer".to_string()))?; + + let expr = parse_expression(expr_pair)?; + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + + Ok(ConstantAst { type_ref, name, expr, span, type_span, name_span }) +} + +fn parse_contract_field_definition<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing field type".to_string()))?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing field name".to_string()))?; + let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing field initializer".to_string()))?; + + let expr = parse_expression(expr_pair)?; + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + + Ok(ContractFieldAst { type_ref, name, expr, span, type_span, name_span }) +} + +fn parse_statement<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); match pair.as_rule() { Rule::statement => { if let Some(inner) = pair.into_inner().next() { parse_statement(inner) } else { - Err(CompilerError::Unsupported("empty statement".to_string())) + Err(CompilerError::Unsupported("empty statement".to_string()).with_span(&span)) } } Rule::variable_definition => { let mut inner = pair.into_inner(); - let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; + let type_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable type".to_string()).with_span(&span))?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair).map_err(|err| err.with_span(&span))?; let mut modifiers = Vec::new(); + let mut modifier_spans = Vec::new(); while let Some(p) = inner.peek() { if p.as_rule() != Rule::modifier { break; } - modifiers.push(inner.next().expect("checked").as_str().to_string()); + let modifier = inner.next().expect("checked"); + modifiers.push(modifier.as_str().to_string()); + modifier_spans.push(Span::from(modifier.as_span())); } - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable name".to_string()))?; - validate_user_identifier(ident.as_str())?; - let expr = inner.next().map(parse_expression).transpose()?; - Ok(Statement::VariableDefinition { type_ref, modifiers, name: ident.as_str().to_string(), expr }) + let ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing variable name".to_string()).with_span(&span))?; + let Identifier { name, span: name_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + let expr = match inner.next() { + Some(expr_pair) => Some(parse_expression(expr_pair).map_err(|err| err.with_span(&span))?), + None => None, + }; + Ok(Statement::VariableDefinition { type_ref, modifiers, name, expr, span, type_span, modifier_spans, name_span }) } Rule::tuple_assignment => { let mut inner = pair.into_inner(); - let left_type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple type".to_string()))?; - let left_type_ref = parse_type_name_pair(left_type_pair)?; - let left_ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple name".to_string()))?; - let right_type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple type".to_string()))?; - let right_type_ref = parse_type_name_pair(right_type_pair)?; - let right_ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple name".to_string()))?; - validate_user_identifier(left_ident.as_str())?; - validate_user_identifier(right_ident.as_str())?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple expression".to_string()))?; - - let expr = parse_expression(expr_pair)?; + let left_type_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple type".to_string()).with_span(&span))?; + let left_ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing left tuple name".to_string()).with_span(&span))?; + let right_type_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple type".to_string()).with_span(&span))?; + let right_ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing right tuple name".to_string()).with_span(&span))?; + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple expression".to_string()).with_span(&span))?; + + let Identifier { name: left_name, span: left_name_span } = + parse_identifier(left_ident).map_err(|err| err.with_span(&span))?; + let Identifier { name: right_name, span: right_name_span } = + parse_identifier(right_ident).map_err(|err| err.with_span(&span))?; + + let right_type_span = Span::from(right_type_pair.as_span()); + let right_type_ref = parse_type_name_pair(right_type_pair).map_err(|err| err.with_span(&span))?; + + let left_type_span = Span::from(left_type_pair.as_span()); + let left_type_ref = parse_type_name_pair(left_type_pair).map_err(|err| err.with_span(&span))?; + + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; Ok(Statement::TupleAssignment { left_type_ref, - left_name: left_ident.as_str().to_string(), + left_name, right_type_ref, - right_name: right_ident.as_str().to_string(), + right_name, expr, + span, + left_type_span, + left_name_span, + right_type_span, + right_name_span, }) } Rule::push_statement => { let mut inner = pair.into_inner(); - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing push target".to_string()))?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing push expression".to_string()))?; - let expr = parse_expression(expr_pair)?; - Ok(Statement::ArrayPush { name: ident.as_str().to_string(), expr }) + let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing push target".to_string()).with_span(&span))?; + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing push expression".to_string()).with_span(&span))?; + let Identifier { name, span: name_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::ArrayPush { name, expr, span, name_span }) + } + Rule::function_call_assignment => { + let mut inner = pair.into_inner(); + let mut bindings = Vec::new(); + while let Some(p) = inner.peek() { + if p.as_rule() != Rule::typed_binding { + break; + } + let binding = inner.next().expect("checked"); + bindings.push(parse_typed_binding(binding).map_err(|err| err.with_span(&span))?); + } + let call_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()).with_span(&span))?; + let (Identifier { name, span: name_span }, args) = + parse_function_call_parts(call_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::FunctionCallAssign { bindings, name, args, span, name_span }) + } + Rule::state_function_call_assignment => { + let mut inner = pair.into_inner(); + let mut bindings = Vec::new(); + while let Some(p) = inner.peek() { + if p.as_rule() != Rule::state_typed_binding { + break; + } + let binding = inner.next().expect("checked"); + bindings.push(parse_state_typed_binding(binding).map_err(|err| err.with_span(&span))?); + } + let call_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()).with_span(&span))?; + let (Identifier { name, span: name_span }, args) = + parse_function_call_parts(call_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::StateFunctionCallAssign { bindings, name, args, span, name_span }) + } + Rule::call_statement => { + let mut inner = pair.into_inner(); + let call_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing call statement".to_string()).with_span(&span))?; + let (Identifier { name, span: name_span }, args) = + parse_function_call_parts(call_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::FunctionCall { name, args, span, name_span }) } Rule::assign_statement => { let mut inner = pair.into_inner(); - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing assignment name".to_string()))?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing assignment expression".to_string()))?; - let expr = parse_expression(expr_pair)?; - Ok(Statement::Assign { name: ident.as_str().to_string(), expr }) + let ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing assignment name".to_string()).with_span(&span))?; + let expr_pair = inner + .next() + .ok_or_else(|| CompilerError::Unsupported("missing assignment expression".to_string()).with_span(&span))?; + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + let Identifier { name, span: name_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + Ok(Statement::Assign { name, expr, span, name_span }) + } + Rule::return_statement => { + let mut inner = pair.into_inner(); + let list_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing return values".to_string()).with_span(&span))?; + let exprs = parse_expression_list(list_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::Return { exprs, span }) } Rule::time_op_statement => { let mut inner = pair.into_inner(); - let tx_var = inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op variable".to_string()))?; - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op expression".to_string()))?; - let message = inner.next().map(parse_require_message).transpose()?; - - let expr = parse_expression(expr_pair)?; - let tx_var = match tx_var.as_str() { + let tx_var = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op variable".to_string()).with_span(&span))?; + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing time op expression".to_string()).with_span(&span))?; + let message = inner.next().map(parse_require_message).transpose().map_err(|err| err.with_span(&span))?; + + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + let tx_var_span = Span::from(tx_var.as_span()); + let tx_var_value = match tx_var.as_str() { "this.age" => TimeVar::ThisAge, "tx.time" => TimeVar::TxTime, - other => return Err(CompilerError::Unsupported(format!("unsupported time variable: {other}"))), + other => { + return Err(CompilerError::Unsupported(format!("unsupported time variable: {other}")).with_span(&tx_var_span)); + } }; - Ok(Statement::TimeOp { tx_var, expr, message }) + let (message, message_span) = message.unzip(); + Ok(Statement::TimeOp { tx_var: tx_var_value, expr, message, span, tx_var_span, message_span }) } Rule::require_statement => { let mut inner = pair.into_inner(); - let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing require expression".to_string()))?; - let message = inner.next().map(parse_require_message).transpose()?; - let expr = parse_expression(expr_pair)?; - Ok(Statement::Require { expr, message }) + let expr_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing require expression".to_string()).with_span(&span))?; + let message = inner.next().map(parse_require_message).transpose().map_err(|err| err.with_span(&span))?; + let expr = parse_expression(expr_pair).map_err(|err| err.with_span(&span))?; + let (message, message_span) = message.unzip(); + Ok(Statement::Require { expr, message, span, message_span }) } Rule::if_statement => { let mut inner = pair.into_inner(); - let cond_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing if condition".to_string()))?; - let cond_expr = parse_expression(cond_pair)?; - let then_block = inner.next().ok_or_else(|| CompilerError::Unsupported("missing if block".to_string()))?; - let then_branch = parse_block(then_block)?; - let else_branch = inner.next().map(parse_block).transpose()?; - Ok(Statement::If { condition: cond_expr, then_branch, else_branch }) - } - Rule::call_statement => { - let mut inner = pair.into_inner(); - let call_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()))?; - match parse_function_call(call_pair)? { - Expr::Call { name, args } => Ok(Statement::FunctionCall { name, args }), - _ => Err(CompilerError::Unsupported("function call expected".to_string())), - } - } - Rule::function_call_assignment => { - let mut bindings = Vec::new(); - let mut call_pair = None; - for item in pair.into_inner() { - if item.as_rule() == Rule::typed_binding { - let mut inner = item.into_inner(); - let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; - let name = inner - .next() - .ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))? - .as_str() - .to_string(); - validate_user_identifier(&name)?; - bindings.push(ParamAst { type_ref, name }); - } else if item.as_rule() == Rule::function_call { - call_pair = Some(item); - } - } - let call_pair = call_pair.ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()))?; - match parse_function_call(call_pair)? { - Expr::Call { name, args } => Ok(Statement::FunctionCallAssign { bindings, name, args }), - _ => Err(CompilerError::Unsupported("function call expected".to_string())), - } - } - Rule::state_function_call_assignment => { - let mut bindings = Vec::new(); - let mut call_pair = None; - for item in pair.into_inner() { - if item.as_rule() == Rule::state_typed_binding { - let mut inner = item.into_inner(); - let field_name = inner - .next() - .ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))? - .as_str() - .to_string(); - let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; - let type_ref = parse_type_name_pair(type_pair)?; - let name = inner - .next() - .ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))? - .as_str() - .to_string(); - validate_user_identifier(&field_name)?; - validate_user_identifier(&name)?; - bindings.push(StateBindingAst { field_name, type_ref, name }); - } else if item.as_rule() == Rule::function_call { - call_pair = Some(item); - } - } - let call_pair = call_pair.ok_or_else(|| CompilerError::Unsupported("missing function call".to_string()))?; - match parse_function_call(call_pair)? { - Expr::Call { name, args } => Ok(Statement::StateFunctionCallAssign { bindings, name, args }), - _ => Err(CompilerError::Unsupported("function call expected".to_string())), - } + let cond_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing if condition".to_string()).with_span(&span))?; + let cond_expr = parse_expression(cond_pair).map_err(|err| err.with_span(&span))?; + let then_block = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing if block".to_string()).with_span(&span))?; + let (then_branch, then_span) = parse_block(then_block).map_err(|err| err.with_span(&span))?; + let else_data = inner.next().map(parse_block).transpose().map_err(|err| err.with_span(&span))?; + let (else_branch, else_span) = match else_data { + Some((branch, span)) => (Some(branch), Some(span)), + None => (None, None), + }; + Ok(Statement::If { condition: cond_expr, then_branch, else_branch, span, then_span, else_span }) } Rule::for_statement => { let mut inner = pair.into_inner(); - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop identifier".to_string()))?; - validate_user_identifier(ident.as_str())?; - let start_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop start".to_string()))?; - let end_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop end".to_string()))?; - let block_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop body".to_string()))?; - - let start_expr = parse_expression(start_pair)?; - let end_expr = parse_expression(end_pair)?; - let body = parse_block(block_pair)?; - - Ok(Statement::For { ident: ident.as_str().to_string(), start: start_expr, end: end_expr, body }) + let ident = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop identifier".to_string()).with_span(&span))?; + let start_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop start".to_string()).with_span(&span))?; + let end_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop end".to_string()).with_span(&span))?; + let block_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing for loop body".to_string()).with_span(&span))?; + + let start_expr = parse_expression(start_pair).map_err(|err| err.with_span(&span))?; + let end_expr = parse_expression(end_pair).map_err(|err| err.with_span(&span))?; + let (body, body_span) = parse_block(block_pair).map_err(|err| err.with_span(&span))?; + let Identifier { name: ident, span: ident_span } = parse_identifier(ident).map_err(|err| err.with_span(&span))?; + + Ok(Statement::For { ident, start: start_expr, end: end_expr, body, span, ident_span, body_span }) } Rule::yield_statement => { let mut inner = pair.into_inner(); - let list_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing yield arguments".to_string()))?; - let args = parse_expression_list(list_pair)?; + let list_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing yield arguments".to_string()).with_span(&span))?; + let args = parse_expression_list(list_pair).map_err(|err| err.with_span(&span))?; if args.len() != 1 { - return Err(CompilerError::Unsupported("yield() expects a single argument".to_string())); - } - Ok(Statement::Yield { expr: args[0].clone() }) - } - Rule::return_statement => { - let mut inner = pair.into_inner(); - let list_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing return arguments".to_string()))?; - let args = parse_expression_list(list_pair)?; - if args.is_empty() { - return Err(CompilerError::Unsupported("return() expects at least one argument".to_string())); + return Err(CompilerError::Unsupported("yield() expects a single argument".to_string()).with_span(&span)); } - Ok(Statement::Return { exprs: args }) + Ok(Statement::Yield { expr: args[0].clone(), span }) } Rule::console_statement => { let mut inner = pair.into_inner(); - let list_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing console arguments".to_string()))?; - let args = parse_console_parameter_list(list_pair)?; - Ok(Statement::Console { args }) + let list_pair = + inner.next().ok_or_else(|| CompilerError::Unsupported("missing console arguments".to_string()).with_span(&span))?; + let args = parse_console_parameter_list(list_pair).map_err(|err| err.with_span(&span))?; + Ok(Statement::Console { args, span }) } - _ => Err(CompilerError::Unsupported(format!("unexpected statement: {:?}", pair.as_rule()))), + _ => Err(CompilerError::Unsupported(format!("unexpected statement: {:?}", pair.as_rule())).with_span(&span)), } } -fn parse_block(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_block<'i>(pair: Pair<'i, Rule>) -> Result<(Vec>, Span<'i>), CompilerError> { + let span = Span::from(pair.as_span()); match pair.as_rule() { Rule::block => { let mut statements = Vec::new(); - for stmt in pair.into_inner() { - statements.push(parse_statement(stmt)?); + let mut block_span: Option> = None; + for stmt_pair in pair.into_inner() { + let stmt = parse_statement(stmt_pair)?; + let stmt_span = stmt.span(); + block_span = Some(match block_span { + None => stmt_span, + Some(prev) => prev.join(&stmt_span), + }); + statements.push(stmt); } - Ok(statements) + Ok((statements, block_span.unwrap_or(span))) + } + _ => { + let stmt = parse_statement(pair)?; + let stmt_span = stmt.span(); + Ok((vec![stmt], stmt_span)) } - _ => Ok(vec![parse_statement(pair)?]), } } -fn parse_console_parameter_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_console_parameter_list<'i>(pair: Pair<'i, Rule>) -> Result>, CompilerError> { let mut args = Vec::new(); + for param in pair.into_inner() { let value = if param.as_rule() == Rule::console_parameter { single_inner(param)? } else { param }; match value.as_rule() { - Rule::Identifier => args.push(ConsoleArg::Identifier(value.as_str().to_string())), + Rule::Identifier => { + let Identifier { name, span } = parse_identifier(value)?; + args.push(ConsoleArg::Identifier(name, span)); + } Rule::literal => args.push(ConsoleArg::Literal(parse_literal(single_inner(value)?)?)), _ => return Err(CompilerError::Unsupported("console.log arguments not supported".to_string())), } @@ -649,15 +1035,45 @@ fn parse_console_parameter_list(pair: Pair<'_, Rule>) -> Result, Ok(args) } -fn parse_require_message(pair: Pair<'_, Rule>) -> Result { +fn parse_typed_binding<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; + let ident_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))?; + + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + let Identifier { name, span: name_span } = parse_identifier(ident_pair)?; + + Ok(ParamAst { type_ref, name, span, type_span, name_span }) +} + +fn parse_require_message<'i>(pair: Pair<'i, Rule>) -> Result<(String, Span<'i>), CompilerError> { let inner = single_inner(pair)?; match parse_string_literal(inner)? { - Expr::String(value) => Ok(value), + Expr { kind: ExprKind::String(value), span } => Ok((value, span)), _ => Err(CompilerError::Unsupported("require message must be a string literal".to_string())), } } -fn parse_expression(pair: Pair<'_, Rule>) -> Result { +fn parse_state_typed_binding<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + + let field_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))?; + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding type".to_string()))?; + let ident_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing binding name".to_string()))?; + + let Identifier { name: field_name, span: field_span } = parse_identifier(field_pair)?; + let type_span = Span::from(type_pair.as_span()); + let type_ref = parse_type_name_pair(type_pair)?; + let Identifier { name, span: name_span } = parse_identifier(ident_pair)?; + + Ok(StateBindingAst { field_name, type_ref, name, span, field_span, type_span, name_span }) +} + +fn parse_expression<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { match pair.as_rule() { Rule::expression => parse_expression(single_inner(pair)?), Rule::logical_or => parse_infix(pair, parse_expression, map_logical_or), @@ -675,11 +1091,14 @@ fn parse_expression(pair: Pair<'_, Rule>) -> Result { Rule::parenthesized => parse_expression(single_inner(pair)?), Rule::literal => parse_literal(single_inner(pair)?), Rule::number_literal => parse_number_literal(pair), - Rule::NumberLiteral => parse_number(pair.as_str()), - Rule::BooleanLiteral => Ok(Expr::Bool(pair.as_str() == "true")), - Rule::HexLiteral => parse_hex_literal(pair.as_str()), - Rule::Identifier => Ok(Expr::Identifier(pair.as_str().to_string())), - Rule::NullaryOp => parse_nullary(pair.as_str()), + Rule::NumberLiteral => parse_number_expr(pair), + Rule::BooleanLiteral => Ok(Expr::new(ExprKind::Bool(pair.as_str() == "true"), Span::from(pair.as_span()))), + Rule::HexLiteral => parse_hex_literal(pair), + Rule::Identifier => { + let Identifier { name, span } = parse_identifier(pair)?; + Ok(Expr::new(ExprKind::Identifier(name), span)) + } + Rule::NullaryOp => parse_nullary(pair.as_str(), Span::from(pair.as_span())), Rule::introspection => parse_introspection(pair), Rule::array => parse_array(pair), Rule::function_call => parse_function_call(pair), @@ -698,7 +1117,8 @@ fn parse_expression(pair: Pair<'_, Rule>) -> Result { } } -fn parse_unary(pair: Pair<'_, Rule>) -> Result { +fn parse_unary<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); let mut ops = Vec::new(); while let Some(op) = inner.peek() { @@ -716,22 +1136,24 @@ fn parse_unary(pair: Pair<'_, Rule>) -> Result { let mut expr = parse_expression(inner.next().ok_or_else(|| CompilerError::Unsupported("missing unary operand".to_string()))?)?; for op in ops.into_iter().rev() { - expr = Expr::Unary { op, expr: Box::new(expr) }; + expr = Expr::new(ExprKind::Unary { op, expr: Box::new(expr) }, span); } Ok(expr) } -fn parse_postfix(pair: Pair<'_, Rule>) -> Result { +fn parse_postfix<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { let mut inner = pair.into_inner(); let primary = inner.next().ok_or_else(|| CompilerError::Unsupported("missing primary in postfix".to_string()))?; let mut expr = parse_primary(primary)?; for postfix in inner { + let postfix_span = Span::from(postfix.as_span()); match postfix.as_rule() { Rule::split_call => { let mut split_inner = postfix.into_inner(); let index_expr = split_inner.next().ok_or_else(|| CompilerError::Unsupported("missing split index".to_string()))?; let index = Box::new(parse_expression(index_expr)?); - expr = Expr::Split { source: Box::new(expr), index, part: SplitPart::Left }; + let span = expr.span.join(&postfix_span); + expr = Expr::new(ExprKind::Split { source: Box::new(expr), index, part: SplitPart::Left, span: postfix_span }, span); } Rule::slice_call => { let mut slice_inner = postfix.into_inner(); @@ -739,34 +1161,39 @@ fn parse_postfix(pair: Pair<'_, Rule>) -> Result { let end_expr = slice_inner.next().ok_or_else(|| CompilerError::Unsupported("missing slice end".to_string()))?; let start = Box::new(parse_expression(start_expr)?); let end = Box::new(parse_expression(end_expr)?); - expr = Expr::Slice { source: Box::new(expr), start, end }; + let span = expr.span.join(&postfix_span); + expr = Expr::new(ExprKind::Slice { source: Box::new(expr), start, end, span: postfix_span }, span); } Rule::tuple_index => { let mut index_inner = postfix.into_inner(); - let index_expr = index_inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple index".to_string()))?; - let index = parse_expression(index_expr)?; - match (&expr, &index) { - (Expr::Split { source, index: split_index, .. }, Expr::Int(0)) => { - expr = Expr::Split { source: source.clone(), index: split_index.clone(), part: SplitPart::Left }; - } - (Expr::Split { source, index: split_index, .. }, Expr::Int(1)) => { - expr = Expr::Split { source: source.clone(), index: split_index.clone(), part: SplitPart::Right }; - } - (Expr::Split { .. }, _) => { - return Err(CompilerError::Unsupported("tuple index must be 0 or 1".to_string())); - } - _ => { - expr = Expr::ArrayIndex { source: Box::new(expr), index: Box::new(index) }; - } + let index_pair = index_inner.next().ok_or_else(|| CompilerError::Unsupported("missing tuple index".to_string()))?; + let index_expr = parse_expression(index_pair)?; + let index_span = index_expr.span; + let span = expr.span.join(&postfix_span); + if let ExprKind::Split { source, index: split_index, span: split_span, .. } = &expr.kind { + let part = match index_expr.kind { + ExprKind::Int(0) => SplitPart::Left, + ExprKind::Int(1) => SplitPart::Right, + _ => { + return Err(CompilerError::Unsupported("split() index must be 0 or 1".to_string()).with_span(&index_span)); + } + }; + expr = Expr::new( + ExprKind::Split { source: source.clone(), index: split_index.clone(), part, span: *split_span }, + span, + ); + } else { + expr = Expr::new(ExprKind::ArrayIndex { source: Box::new(expr), index: Box::new(index_expr) }, span); } } Rule::unary_suffix => { - let text = postfix.as_str(); - if text.ends_with("length") { - expr = Expr::Call { name: "length".to_string(), args: vec![expr] }; - } else { - return Err(CompilerError::Unsupported("postfix operators are not supported".to_string())); - } + let kind = match postfix.as_str() { + ".reverse()" => UnarySuffixKind::Reverse, + ".length" => UnarySuffixKind::Length, + other => return Err(CompilerError::Unsupported(format!("unknown unary suffix '{other}'"))), + }; + let span = expr.span.join(&postfix_span); + expr = Expr::new(ExprKind::UnarySuffix { source: Box::new(expr), kind, span: postfix_span }, span); } _ => { return Err(CompilerError::Unsupported("postfix operators are not supported".to_string())); @@ -776,39 +1203,51 @@ fn parse_postfix(pair: Pair<'_, Rule>) -> Result { Ok(expr) } -fn parse_typed_parameter_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_typed_parameter_list<'i>(pair: Pair<'i, Rule>) -> Result>, CompilerError> { let mut params = Vec::new(); for param in pair.into_inner() { if param.as_rule() != Rule::parameter { continue; } + + let param_span = Span::from(param.as_span()); let mut inner = param.into_inner(); + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing parameter type".to_string()))?; + let ident_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing parameter name".to_string()))?; + + let Identifier { name, span: name_span } = parse_identifier(ident_pair)?; + let type_span = Span::from(type_pair.as_span()); let type_ref = parse_type_name_pair(type_pair)?; - let ident = inner.next().ok_or_else(|| CompilerError::Unsupported("missing parameter name".to_string()))?.as_str().to_string(); - validate_user_identifier(&ident)?; - params.push(ParamAst { type_ref, name: ident }); + + params.push(ParamAst { type_ref, name, span: param_span, type_span, name_span }); } Ok(params) } -fn parse_return_type_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { - let mut types = Vec::new(); - for item in pair.into_inner() { - if item.as_rule() == Rule::type_name { - let type_ref = parse_type_name_pair(item)?; - types.push(type_ref); +fn parse_return_type_list<'i>(pair: Pair<'i, Rule>) -> Result<(Vec, Vec>), CompilerError> { + let mut return_types = Vec::new(); + let mut return_spans = Vec::new(); + for user_type in pair.into_inner() { + if user_type.as_rule() != Rule::type_name { + continue; } + let type_span = Span::from(user_type.as_span()); + return_types.push(parse_type_name_pair(user_type)?); + return_spans.push(type_span); } - Ok(types) + Ok((return_types, return_spans)) } -fn parse_primary(pair: Pair<'_, Rule>) -> Result { +fn parse_primary<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { match pair.as_rule() { Rule::parenthesized => parse_expression(single_inner(pair)?), Rule::literal => parse_literal(single_inner(pair)?), - Rule::Identifier => Ok(Expr::Identifier(pair.as_str().to_string())), - Rule::NullaryOp => parse_nullary(pair.as_str()), + Rule::Identifier => { + let Identifier { name, span } = parse_identifier(pair)?; + Ok(Expr::new(ExprKind::Identifier(name), span)) + } + Rule::NullaryOp => parse_nullary(pair.as_str(), Span::from(pair.as_span())), Rule::introspection => parse_introspection(pair), Rule::array => parse_array(pair), Rule::function_call => parse_function_call(pair), @@ -820,87 +1259,115 @@ fn parse_primary(pair: Pair<'_, Rule>) -> Result { } } -fn parse_state_object(pair: Pair<'_, Rule>) -> Result { +fn parse_state_object<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut fields = Vec::new(); for field_pair in pair.into_inner() { if field_pair.as_rule() != Rule::state_entry { continue; } + let field_span = Span::from(field_pair.as_span()); let mut inner = field_pair.into_inner(); - let name = - inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))?.as_str().to_string(); - validate_user_identifier(&name)?; + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field name".to_string()))?; let expr_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing state field expression".to_string()))?; + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; let expr = parse_expression(expr_pair)?; - fields.push(StateFieldExpr { name, expr }); + fields.push(StateFieldExpr { name, expr, span: field_span, name_span }); } - Ok(Expr::StateObject(fields)) + Ok(Expr::new(ExprKind::StateObject(fields), span)) } -fn parse_literal(pair: Pair<'_, Rule>) -> Result { +fn parse_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { match pair.as_rule() { - Rule::BooleanLiteral => Ok(Expr::Bool(pair.as_str() == "true")), + Rule::BooleanLiteral => Ok(Expr::new(ExprKind::Bool(pair.as_str() == "true"), Span::from(pair.as_span()))), Rule::number_literal => parse_number_literal(pair), - Rule::NumberLiteral => parse_number(pair.as_str()), - Rule::HexLiteral => parse_hex_literal(pair.as_str()), + Rule::NumberLiteral => parse_number_expr(pair), + Rule::HexLiteral => parse_hex_literal(pair), Rule::StringLiteral => parse_string_literal(pair), Rule::DateLiteral => parse_date_literal(pair), _ => Err(CompilerError::Unsupported(format!("literal not supported: {:?}", pair.as_rule()))), } } -fn parse_number(raw: &str) -> Result { - let cleaned = raw.replace('_', ""); - if let Some((base_str, exp_str)) = cleaned.split_once('e').or_else(|| cleaned.split_once('E')) { - if exp_str.is_empty() { - return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); - } - let base: i64 = base_str.parse().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - let exp: i64 = exp_str.parse().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - if exp < 0 { - return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); - } - let pow = 10i128.pow(exp as u32); - let value = - (base as i128).checked_mul(pow).ok_or_else(|| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - if value > i64::MAX as i128 || value < i64::MIN as i128 { - return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); - } - return Ok(Expr::Int(value as i64)); +fn parse_number_expr<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let value = parse_number(pair.as_str())?; + Ok(Expr::new(ExprKind::Int(value), span)) +} + +fn parse_number(raw: &str) -> Result { + let raw = raw.trim(); + let mut parts = raw.split(['e', 'E']); + let base_raw = parts.next().unwrap_or(""); + let exp_raw = parts.next(); + + // nothing allowed after having the exponent + if parts.next().is_some() { + return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); + } + + let base_clean = base_raw.replace('_', ""); + if base_clean.is_empty() || base_clean == "-" { + return Err(CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'"))); + } + let mut value = + base_clean.parse::().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; + + if let Some(exp_raw) = exp_raw { + let exp_clean = exp_raw.replace('_', ""); + + // rejects negative exponent + let exp = exp_clean.parse::().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; + let pow = 10i128.checked_pow(exp).ok_or_else(|| CompilerError::InvalidLiteral(format!("number literal overflow '{raw}'")))?; + value = value.checked_mul(pow).ok_or_else(|| CompilerError::InvalidLiteral(format!("number literal overflow '{raw}'")))?; } - let value: i64 = cleaned.parse().map_err(|_| CompilerError::InvalidLiteral(format!("invalid number literal '{raw}'")))?; - Ok(Expr::Int(value)) + + if value < i64::MIN as i128 || value > i64::MAX as i128 { + return Err(CompilerError::InvalidLiteral(format!("number literal overflow '{raw}'"))); + } + + Ok(value as i64) } -fn parse_array(pair: Pair<'_, Rule>) -> Result { +fn parse_array<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut values = Vec::new(); for expr_pair in pair.into_inner() { values.push(parse_expression(expr_pair)?); } - Ok(Expr::Array(values)) + Ok(Expr::new(ExprKind::Array(values), span)) } -fn parse_function_call(pair: Pair<'_, Rule>) -> Result { +fn parse_function_call_parts<'i>(pair: Pair<'i, Rule>) -> Result<(Identifier<'i>, Vec>), CompilerError> { let mut inner = pair.into_inner(); - let name = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?.as_str().to_string(); + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing function name".to_string()))?; let args = match inner.next() { Some(list) => parse_expression_list(list)?, None => Vec::new(), }; - Ok(Expr::Call { name, args }) + let name = parse_identifier(name_pair)?; + Ok((name, args)) } -fn parse_instantiation(pair: Pair<'_, Rule>) -> Result { +fn parse_function_call<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let (Identifier { name, span: name_span }, args) = parse_function_call_parts(pair)?; + Ok(Expr::new(ExprKind::Call { name, args, name_span }, span)) +} + +fn parse_instantiation<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); - let name = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constructor name".to_string()))?.as_str().to_string(); + let name_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing constructor name".to_string()))?; let args = match inner.next() { Some(list) => parse_expression_list(list)?, None => Vec::new(), }; - Ok(Expr::New { name, args }) + let Identifier { name, span: name_span } = parse_identifier(name_pair)?; + Ok(Expr::new(ExprKind::New { name, args, name_span }, span)) } -fn parse_expression_list(pair: Pair<'_, Rule>) -> Result, CompilerError> { +fn parse_expression_list<'i>(pair: Pair<'i, Rule>) -> Result>, CompilerError> { let mut args = Vec::new(); for expr_pair in pair.into_inner() { args.push(parse_expression(expr_pair)?); @@ -908,56 +1375,64 @@ fn parse_expression_list(pair: Pair<'_, Rule>) -> Result, CompilerErro Ok(args) } -fn parse_cast(pair: Pair<'_, Rule>) -> Result { +fn parse_cast<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); - let type_name = inner.next().ok_or_else(|| CompilerError::Unsupported("missing cast type".to_string()))?.as_str().to_string(); - let args = match inner.next() { - Some(list) => parse_expression_list(list)?, - None => Vec::new(), - }; + + let type_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing cast type".to_string()))?; + let type_name = type_pair.as_str().trim().to_string(); + let type_span = Span::from(type_pair.as_span()); + + let mut args = Vec::new(); + for part in inner { + args.push(parse_expression(part)?); + } + if type_name == "bytes" { - return Ok(Expr::Call { name: "bytes".to_string(), args }); + return Ok(Expr::new(ExprKind::Call { name: "bytes".to_string(), args, name_span: type_span }, span)); } + if type_name == "byte" { - return Ok(Expr::Call { name: "byte[1]".to_string(), args }); + return Ok(Expr::new(ExprKind::Call { name: "byte[1]".to_string(), args, name_span: type_span }, span)); } + if type_name == "int" { - return Ok(Expr::Call { name: "int".to_string(), args }); + return Ok(Expr::new(ExprKind::Call { name: "int".to_string(), args, name_span: type_span }, span)); } + if matches!(type_name.as_str(), "sig" | "pubkey" | "datasig") { - return Ok(Expr::Call { name: type_name, args }); + return Ok(Expr::new(ExprKind::Call { name: type_name, args, name_span: type_span }, span)); } + // Handle single byte cast (duplicate check removed above) // Support type[N] syntax if let Some(bracket_pos) = type_name.find('[') { if type_name.ends_with(']') { - let _base_type = &type_name[..bracket_pos]; let size_str = &type_name[bracket_pos + 1..type_name.len() - 1]; - // Support both type[N] and type[] (dynamic array) - if size_str.is_empty() { - // Dynamic array cast like byte[] - return Ok(Expr::Call { name: type_name.to_string(), args }); - } else if let Ok(_size) = size_str.parse::() { - // Fixed-size array cast like byte[32] - return Ok(Expr::Call { name: type_name.to_string(), args }); + if size_str.is_empty() || size_str.parse::().is_ok() { + return Ok(Expr::new(ExprKind::Call { name: type_name, args, name_span: type_span }, span)); } } } + Err(CompilerError::Unsupported(format!("cast type not supported: {type_name}"))) } -fn parse_number_literal(pair: Pair<'_, Rule>) -> Result { +fn parse_number_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let mut inner = pair.into_inner(); let number = inner.next().ok_or_else(|| CompilerError::InvalidLiteral("missing number literal".to_string()))?; let value = parse_number(number.as_str())?; - if let Some(unit_pair) = inner.next() { - let unit = unit_pair.as_str(); - return apply_number_unit(value, unit); + let expr = Expr::new(ExprKind::Int(value), span); + if let Some(unit) = inner.next() { + return apply_number_unit(expr, unit.as_str()); } - Ok(value) + Ok(expr) } -fn parse_hex_literal(raw: &str) -> Result { +fn parse_hex_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let raw = pair.as_str(); let trimmed = raw.trim_start_matches("0x").trim_start_matches("0X"); let normalized = if trimmed.len() % 2 != 0 { format!("0{trimmed}") } else { trimmed.to_string() }; let bytes = (0..normalized.len()) @@ -965,13 +1440,13 @@ fn parse_hex_literal(raw: &str) -> Result { .map(|i| u8::from_str_radix(&normalized[i..i + 2], 16)) .collect::, _>>() .map_err(|_| CompilerError::InvalidLiteral(format!("invalid hex literal '{raw}'")))?; - // Convert Vec to Expr::Array of Expr::Byte - Ok(Expr::Array(bytes.into_iter().map(Expr::Byte).collect())) + Ok(Expr::new(ExprKind::Array(bytes.into_iter().map(|byte| Expr::new(ExprKind::Byte(byte), span)).collect()), span)) } -fn apply_number_unit(expr: Expr, unit: &str) -> Result { - let value = match expr { - Expr::Int(value) => value, +fn apply_number_unit<'i>(expr: Expr<'i>, unit: &str) -> Result, CompilerError> { + let span = expr.span; + let value = match expr.kind { + ExprKind::Int(value) => value, _ => return Err(CompilerError::InvalidLiteral("number literal is not an int".to_string())), }; let multiplier = match unit { @@ -985,41 +1460,37 @@ fn apply_number_unit(expr: Expr, unit: &str) -> Result { "kas" => 100_000_000, _ => return Err(CompilerError::Unsupported(format!("number unit '{unit}' not supported"))), }; - Ok(Expr::Int(value.saturating_mul(multiplier))) + Ok(Expr::new(ExprKind::Int(value.saturating_mul(multiplier)), span)) } -fn parse_date_literal(pair: Pair<'_, Rule>) -> Result { - let raw = pair.as_str(); - let start = raw - .find('"') - .or_else(|| raw.find('\'')) - .ok_or_else(|| CompilerError::InvalidLiteral("date literal missing quotes".to_string()))?; - let quote = raw.as_bytes()[start] as char; - let end = raw[start + 1..] - .find(quote) - .map(|idx| idx + start + 1) - .ok_or_else(|| CompilerError::InvalidLiteral("date literal missing closing quote".to_string()))?; - let value = &raw[start + 1..end]; - - let timestamp = NaiveDateTime::parse_from_str(value, "%Y-%m-%dT%H:%M:%S") - .map_err(|_| CompilerError::InvalidLiteral("invalid date literal".to_string()))? +fn parse_date_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let mut inner = pair.into_inner(); + let string_pair = inner.next().ok_or_else(|| CompilerError::InvalidLiteral("missing date literal".to_string()))?; + let value = match parse_string_literal(string_pair)? { + Expr { kind: ExprKind::String(value), .. } => value, + _ => return Err(CompilerError::InvalidLiteral("invalid date literal".to_string())), + }; + let timestamp = NaiveDateTime::parse_from_str(&value, "%Y-%m-%dT%H:%M:%S") + .map_err(|_| CompilerError::InvalidLiteral(format!("invalid date literal '{value}'")))? .and_utc() .timestamp(); - Ok(Expr::Int(timestamp)) + Ok(Expr::new(ExprKind::DateLiteral(timestamp), span)) } -fn parse_string_literal(pair: Pair<'_, Rule>) -> Result { +fn parse_string_literal<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let raw = pair.as_str(); - let unquoted = if raw.starts_with('"') && raw.ends_with('"') || raw.starts_with('\'') && raw.ends_with('\'') { + let unquoted = if (raw.starts_with('"') && raw.ends_with('"')) || (raw.starts_with('\'') && raw.ends_with('\'')) { &raw[1..raw.len() - 1] } else { raw }; let unescaped = unquoted.replace("\\\"", "\"").replace("\\'", "'"); - Ok(Expr::String(unescaped)) + Ok(Expr::new(ExprKind::String(unescaped), span)) } -fn parse_nullary(raw: &str) -> Result { +fn parse_nullary<'i>(raw: &str, span: Span<'i>) -> Result, CompilerError> { let op = match raw { "this.activeInputIndex" => NullaryOp::ActiveInputIndex, "this.activeScriptPubKey" => NullaryOp::ActiveScriptPubKey, @@ -1031,45 +1502,49 @@ fn parse_nullary(raw: &str) -> Result { "tx.locktime" => NullaryOp::TxLockTime, _ => return Err(CompilerError::Unsupported(format!("unknown nullary op: {raw}"))), }; - Ok(Expr::Nullary(op)) + Ok(Expr::new(ExprKind::Nullary(op), span)) } -fn parse_introspection(pair: Pair<'_, Rule>) -> Result { +fn parse_introspection<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); let text = pair.as_str(); let mut inner = pair.into_inner(); let index_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing introspection index".to_string()))?; let field_pair = inner.next().ok_or_else(|| CompilerError::Unsupported("missing introspection field".to_string()))?; let index = Box::new(parse_expression(index_pair)?); - let field = field_pair.as_str(); - + let field_raw = field_pair.as_str(); let kind = if text.starts_with("tx.inputs") { - match field { + match field_raw { ".value" => IntrospectionKind::InputValue, ".scriptPubKey" => IntrospectionKind::InputScriptPubKey, ".sigScript" => IntrospectionKind::InputSigScript, - _ => return Err(CompilerError::Unsupported(format!("input field '{field}' not supported"))), + // TODO: support this + ".outpointTransactionHash" => IntrospectionKind::InputOutpointTransactionHash, + ".outpointIndex" => IntrospectionKind::InputOutpointIndex, + ".sequenceNumber" => IntrospectionKind::InputSequenceNumber, + _ => return Err(CompilerError::Unsupported(format!("input field '{field_raw}' not supported"))), } } else if text.starts_with("tx.outputs") { - match field { + match field_raw { ".value" => IntrospectionKind::OutputValue, ".scriptPubKey" => IntrospectionKind::OutputScriptPubKey, - _ => return Err(CompilerError::Unsupported(format!("output field '{field}' not supported"))), + _ => return Err(CompilerError::Unsupported(format!("output field '{field_raw}' not supported"))), } } else { return Err(CompilerError::Unsupported("unknown introspection root".to_string())); }; - Ok(Expr::Introspection { kind, index }) + Ok(Expr::new(ExprKind::Introspection { kind, index, field_span: Span::from(field_pair.as_span()) }, span)) } fn single_inner(pair: Pair<'_, Rule>) -> Result, CompilerError> { pair.into_inner().next().ok_or_else(|| CompilerError::Unsupported("expected inner pair".to_string())) } -fn parse_infix(pair: Pair<'_, Rule>, mut parse_operand: F, mut map_op: G) -> Result +fn parse_infix<'i, F, G>(pair: Pair<'i, Rule>, mut parse_operand: F, mut map_op: G) -> Result, CompilerError> where - F: FnMut(Pair<'_, Rule>) -> Result, + F: FnMut(Pair<'i, Rule>) -> Result, CompilerError>, G: FnMut(Pair<'_, Rule>) -> Result, { let mut inner = pair.into_inner(); @@ -1080,7 +1555,8 @@ where let rhs = inner.next().ok_or_else(|| CompilerError::Unsupported("missing infix rhs".to_string()))?; let op = map_op(op_pair)?; let rhs_expr = parse_operand(rhs)?; - expr = Expr::Binary { op, left: Box::new(expr), right: Box::new(rhs_expr) }; + let span = expr.span.join(&rhs_expr.span); + expr = Expr::new(ExprKind::Binary { op, left: Box::new(expr), right: Box::new(rhs_expr) }, span); } Ok(expr) @@ -1167,3 +1643,15 @@ fn map_factor(pair: Pair<'_, Rule>) -> Result { _ => Err(CompilerError::Unsupported("unexpected factor operator".to_string())), } } + +// validate user input +fn parse_identifier<'i>(pair: Pair<'i, Rule>) -> Result, CompilerError> { + let span = Span::from(pair.as_span()); + let value = pair.as_str().to_string(); + + if value.starts_with("__") { + return Err(CompilerError::Unsupported("identifiers starting with '__' are reserved".to_string())); + } + + Ok(Identifier { name: value, span }) +} diff --git a/silverscript-lang/src/bin/silverc.rs b/silverscript-lang/src/bin/silverc.rs index fbd89538..668d144f 100644 --- a/silverscript-lang/src/bin/silverc.rs +++ b/silverscript-lang/src/bin/silverc.rs @@ -1,10 +1,42 @@ -use std::env; +use std::ffi::OsStr; use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; -use silverscript_lang::ast::Expr; +use clap::Parser; +use silverscript_lang::ast::{Expr, parse_contract_ast}; use silverscript_lang::compiler::{CompileOptions, compile_contract}; +#[derive(Debug, Parser)] +#[command( + name = "silverc", + about = "Compile SilverScript contracts into JSON artifacts", + long_about = "Compile a SilverScript source file into a compiled JSON artifact, or parse only and emit AST JSON.\n\ +\n\ +Default Destination: .json (or _ast.json with --ast-only)\n", + after_help = "Examples:\n\ + silverc contract.sil\n\ + silverc contract.sil -o artifact.json\n\ + silverc contract.sil -c", + next_line_help = true +)] +struct Cli { + /// Source SilverScript file (e.g. contract.sil) + #[arg(value_name = "SOURCE.sil")] + src: PathBuf, + /// Path to JSON constructor arguments + #[arg(visible_alias = "ctor", long = "constructor-args", value_name = "CTOR.json")] + constructor_args: Option, + /// Output file path for JSON output + #[arg(short = 'o', long = "output", value_name = "FILE.json")] + out: Option, + /// Write JSON output to stdout + #[arg(short = 'c', long = "stdout")] + stdout: bool, + /// Parse source and emit AST JSON without compiling + #[arg(long = "ast-only")] + ast_only: bool, +} + fn main() { if let Err(err) = run() { eprintln!("{err}"); @@ -13,47 +45,34 @@ fn main() { } fn run() -> Result<(), String> { - let args = env::args().skip(1).collect::>(); - if args.is_empty() { - return Err("usage: silverc [--constructor-args ctor.json] [-o dst.json]".to_string()); - } - - let mut src: Option = None; - let mut ctor_args_path: Option = None; - let mut out_path: Option = None; - - let mut i = 0; - while i < args.len() { - match args[i].as_str() { - "--constructor-args" => { - let value = args.get(i + 1).ok_or_else(|| "--constructor-args requires a path".to_string())?; - ctor_args_path = Some(value.clone()); - i += 2; - } - "-o" => { - let value = args.get(i + 1).ok_or_else(|| "-o requires a path".to_string())?; - out_path = Some(value.clone()); - i += 2; - } - value if value.starts_with('-') => { - return Err(format!("unknown option: {value}")); - } - value => { - if src.is_some() { - return Err("only one source file is supported".to_string()); - } - src = Some(value.to_string()); - i += 1; - } + let cli = match Cli::try_parse() { + Ok(cli) => cli, + Err(err) if err.use_stderr() => return Err(err.to_string()), + Err(err) => { + err.print().map_err(|print_err| format!("failed to print clap output: {print_err}"))?; + return Ok(()); } + }; + + // both stdout and file output were requested, invalid usage + if cli.stdout && cli.out.is_some() { + return Err("invalid usage: both stdout and file output arguments were provided; pick only one".to_string()); } - let src = src.ok_or_else(|| "missing source file".to_string())?; - let source = fs::read_to_string(&src).map_err(|err| format!("failed to read {src}: {err}"))?; + let source = fs::read_to_string(&cli.src).map_err(|err| format!("failed to read {}: {err}", cli.src.display()))?; - let constructor_args = if let Some(path) = ctor_args_path { - let json = fs::read_to_string(&path).map_err(|err| format!("failed to read {path}: {err}"))?; - serde_json::from_str::>(&json).map_err(|err| format!("failed to parse constructor args {path}: {err}"))? + if cli.ast_only { + let ast = parse_contract_ast(&source).map_err(|err| format!("parse error: {err}"))?; + let rendered = ast.to_string(); + let target = resolve_output_target(&cli, &cli.src, true); + emit_output(&rendered, target)?; + return Ok(()); + } + + let constructor_args = if let Some(path) = &cli.constructor_args { + let json = fs::read_to_string(path).map_err(|err| format!("failed to read {}: {err}", path.display()))?; + serde_json::from_str::>(&json) + .map_err(|err| format!("failed to parse constructor args {}: {err}", path.display()))? } else { Vec::new() }; @@ -61,21 +80,48 @@ fn run() -> Result<(), String> { let compiled = compile_contract(&source, &constructor_args, CompileOptions::default()).map_err(|err| format!("compile error: {err}"))?; - let output_path = match out_path { - Some(path) => PathBuf::from(path), - None => default_output_path(&src), - }; - let json = serde_json::to_string_pretty(&compiled).map_err(|err| format!("failed to serialize output: {err}"))?; - fs::write(&output_path, json).map_err(|err| format!("failed to write {}: {err}", output_path.display()))?; + let target = resolve_output_target(&cli, &cli.src, false); + emit_output(&json, target)?; Ok(()) } -fn default_output_path(src: &str) -> PathBuf { - if let Some(stripped) = src.strip_suffix(".sil") { - PathBuf::from(format!("{stripped}.json")) - } else { - PathBuf::from(format!("{src}.json")) +enum OutputTarget { + Stdout, + File(PathBuf), +} + +fn resolve_output_target(cli: &Cli, src: &Path, ast_only: bool) -> OutputTarget { + if cli.stdout { + return OutputTarget::Stdout; + } + if let Some(path) = &cli.out { + return OutputTarget::File(path.clone()); } + OutputTarget::File(default_output_path(src, ast_only)) +} + +fn emit_output(content: &str, target: OutputTarget) -> Result<(), String> { + match target { + OutputTarget::Stdout => { + println!("{content}"); + Ok(()) + } + OutputTarget::File(path) => { + fs::write(&path, content).map_err(|err| format!("failed to write {}: {err}", path.display()))?; + Ok(()) + } + } +} + +fn default_output_path(src: &Path, ast_only: bool) -> PathBuf { + if !ast_only { + return src.with_extension("json"); + } + + let stem = src.file_stem().or_else(|| src.file_name()).unwrap_or(OsStr::new("output")); + let mut file_name = stem.to_os_string(); + file_name.push("_ast.json"); + src.with_file_name(file_name) } diff --git a/silverscript-lang/src/compiler.rs b/silverscript-lang/src/compiler.rs index cb9ba11a..e9e4d9dd 100644 --- a/silverscript-lang/src/compiler.rs +++ b/silverscript-lang/src/compiler.rs @@ -1,32 +1,16 @@ use std::collections::{HashMap, HashSet}; use kaspa_txscript::opcodes::codes::*; -use kaspa_txscript::script_builder::{ScriptBuilder, ScriptBuilderError}; +use kaspa_txscript::script_builder::ScriptBuilder; use serde::{Deserialize, Serialize}; -use thiserror::Error; use crate::ast::{ - ArrayDim, BinaryOp, ContractAst, ContractFieldAst, Expr, FunctionAst, IntrospectionKind, NullaryOp, SplitPart, StateBindingAst, - Statement, TimeVar, TypeBase, TypeRef, UnaryOp, parse_contract_ast, parse_type_ref, + ArrayDim, BinaryOp, ContractAst, ContractFieldAst, Expr, ExprKind, FunctionAst, IntrospectionKind, NullaryOp, SplitPart, + StateBindingAst, StateFieldExpr, Statement, TimeVar, TypeBase, TypeRef, UnaryOp, UnarySuffixKind, parse_contract_ast, + parse_type_ref, }; -use crate::parser::Rule; -use chrono::NaiveDateTime; - -#[derive(Debug, Error)] -pub enum CompilerError { - #[error("parse error: {0}")] - Parse(#[from] pest::error::Error), - #[error("unsupported feature: {0}")] - Unsupported(String), - #[error("invalid literal: {0}")] - InvalidLiteral(String), - #[error("undefined identifier: {0}")] - UndefinedIdentifier(String), - #[error("cyclic identifier reference: {0}")] - CyclicIdentifier(String), - #[error("script build error: {0}")] - ScriptBuild(#[from] ScriptBuilderError), -} +pub use crate::errors::{CompilerError, ErrorSpan}; +use crate::span; #[derive(Debug, Clone, Copy, Default)] pub struct CompileOptions { @@ -46,32 +30,34 @@ pub struct FunctionAbiEntry { pub inputs: Vec, } -pub type FunctionAbi = Vec; - #[derive(Debug, Serialize, Deserialize)] -pub struct CompiledContract { +pub struct CompiledContract<'i> { pub contract_name: String, pub script: Vec, - pub ast: ContractAst, - pub abi: FunctionAbi, + pub ast: ContractAst<'i>, + pub abi: Vec, pub without_selector: bool, } -pub fn compile_contract(source: &str, constructor_args: &[Expr], options: CompileOptions) -> Result { +pub fn compile_contract<'i>( + source: &'i str, + constructor_args: &[Expr<'i>], + options: CompileOptions, +) -> Result, CompilerError> { let contract = parse_contract_ast(source)?; compile_contract_ast(&contract, constructor_args, options) } -pub fn compile_contract_ast( - contract: &ContractAst, - constructor_args: &[Expr], +pub fn compile_contract_ast<'i>( + contract: &ContractAst<'i>, + constructor_args: &[Expr<'i>], options: CompileOptions, -) -> Result { +) -> Result, CompilerError> { if contract.functions.is_empty() { return Err(CompilerError::Unsupported("contract has no functions".to_string())); } - let entrypoint_functions: Vec<&FunctionAst> = contract.functions.iter().filter(|func| func.entrypoint).collect(); + let entrypoint_functions: Vec<&FunctionAst<'i>> = contract.functions.iter().filter(|func| func.entrypoint).collect(); if entrypoint_functions.is_empty() { return Err(CompilerError::Unsupported("contract has no entrypoint functions".to_string())); } @@ -89,7 +75,8 @@ pub fn compile_contract_ast( let without_selector = entrypoint_functions.len() == 1; - let mut constants = contract.constants.clone(); + let mut constants: HashMap> = + contract.constants.iter().map(|constant| (constant.name.clone(), constant.expr.clone())).collect(); for (param, value) in contract.params.iter().zip(constructor_args.iter()) { constants.insert(param.name.clone(), value.clone()); } @@ -97,7 +84,7 @@ pub fn compile_contract_ast( let functions_map = contract.functions.iter().cloned().map(|func| (func.name.clone(), func)).collect::>(); let function_order = contract.functions.iter().enumerate().map(|(index, func)| (func.name.clone(), index)).collect::>(); - let abi = build_function_abi(contract); + let function_abi_entries = build_function_abi_entries(contract); let uses_script_size = contract_uses_script_size(contract); let mut script_size = if uses_script_size { Some(100i64) } else { None }; @@ -162,7 +149,7 @@ pub fn compile_contract_ast( contract_name: contract.name.clone(), script, ast: contract.clone(), - abi, + abi: function_abi_entries, without_selector, }); } @@ -173,7 +160,7 @@ pub fn compile_contract_ast( contract_name: contract.name.clone(), script, ast: contract.clone(), - abi, + abi: function_abi_entries, without_selector, }); } @@ -183,8 +170,8 @@ pub fn compile_contract_ast( Err(CompilerError::Unsupported("script size did not stabilize".to_string())) } -fn contract_uses_script_size(contract: &ContractAst) -> bool { - if contract.constants.values().any(expr_uses_script_size) { +fn contract_uses_script_size<'i>(contract: &ContractAst<'i>) -> bool { + if contract.constants.iter().any(|constant| expr_uses_script_size(&constant.expr)) { return true; } if contract.fields.iter().any(|field| expr_uses_script_size(&field.expr)) { @@ -193,12 +180,12 @@ fn contract_uses_script_size(contract: &ContractAst) -> bool { contract.functions.iter().any(|func| func.body.iter().any(statement_uses_script_size)) } -fn compile_contract_fields( - fields: &[ContractFieldAst], - base_constants: &HashMap, +fn compile_contract_fields<'i>( + fields: &[ContractFieldAst<'i>], + base_constants: &HashMap>, options: CompileOptions, script_size: Option, -) -> Result<(HashMap, Vec), CompilerError> { +) -> Result<(HashMap>, Vec), CompilerError> { let mut env = base_constants.clone(); let mut field_values = HashMap::new(); let mut field_types = HashMap::new(); @@ -224,7 +211,7 @@ fn compile_contract_fields( let mut compile_visiting = HashSet::new(); let mut stack_depth = 0i64; if field.type_ref.array_dims.is_empty() && field.type_ref.base == TypeBase::Int { - let Expr::Int(value) = resolved else { + let ExprKind::Int(value) = &resolved.kind else { return Err(CompilerError::Unsupported(format!("contract field '{}' expects compile-time int value", field.name))); }; builder.add_data(&value.to_le_bytes())?; @@ -252,18 +239,18 @@ fn compile_contract_fields( Ok((field_values, builder.drain())) } -fn statement_uses_script_size(stmt: &Statement) -> bool { +fn statement_uses_script_size(stmt: &Statement<'_>) -> bool { match stmt { Statement::VariableDefinition { expr, .. } => expr.as_ref().is_some_and(expr_uses_script_size), Statement::TupleAssignment { expr, .. } => expr_uses_script_size(expr), Statement::ArrayPush { expr, .. } => expr_uses_script_size(expr), - Statement::FunctionCall { name, args } => name == "validateOutputState" || args.iter().any(expr_uses_script_size), + Statement::FunctionCall { name, args, .. } => name == "validateOutputState" || args.iter().any(expr_uses_script_size), Statement::FunctionCallAssign { args, .. } => args.iter().any(expr_uses_script_size), Statement::StateFunctionCallAssign { name, args, .. } => name == "readInputState" || args.iter().any(expr_uses_script_size), Statement::Assign { expr, .. } => expr_uses_script_size(expr), Statement::TimeOp { expr, .. } => expr_uses_script_size(expr), Statement::Require { expr, .. } => expr_uses_script_size(expr), - Statement::If { condition, then_branch, else_branch } => { + Statement::If { condition, then_branch, else_branch, .. } => { expr_uses_script_size(condition) || then_branch.iter().any(statement_uses_script_size) || else_branch.as_ref().is_some_and(|branch| branch.iter().any(statement_uses_script_size)) @@ -271,89 +258,90 @@ fn statement_uses_script_size(stmt: &Statement) -> bool { Statement::For { start, end, body, .. } => { expr_uses_script_size(start) || expr_uses_script_size(end) || body.iter().any(statement_uses_script_size) } - Statement::Yield { expr } => expr_uses_script_size(expr), - Statement::Return { exprs } => exprs.iter().any(expr_uses_script_size), - Statement::Console { args } => args.iter().any(|arg| match arg { - crate::ast::ConsoleArg::Identifier(_) => false, + Statement::Yield { expr, .. } => expr_uses_script_size(expr), + Statement::Return { exprs, .. } => exprs.iter().any(expr_uses_script_size), + Statement::Console { args, .. } => args.iter().any(|arg| match arg { + crate::ast::ConsoleArg::Identifier(_, _) => false, crate::ast::ConsoleArg::Literal(expr) => expr_uses_script_size(expr), }), } } -fn expr_uses_script_size(expr: &Expr) -> bool { - match expr { - Expr::Nullary(NullaryOp::ThisScriptSize) => true, - Expr::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, - Expr::Unary { expr, .. } => expr_uses_script_size(expr), - Expr::Binary { left, right, .. } => expr_uses_script_size(left) || expr_uses_script_size(right), - Expr::IfElse { condition, then_expr, else_expr } => { +fn expr_uses_script_size<'i>(expr: &Expr<'i>) -> bool { + match &expr.kind { + ExprKind::Nullary(NullaryOp::ThisScriptSize) => true, + ExprKind::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, + ExprKind::Unary { expr, .. } => expr_uses_script_size(expr), + ExprKind::Binary { left, right, .. } => expr_uses_script_size(left) || expr_uses_script_size(right), + ExprKind::IfElse { condition, then_expr, else_expr } => { expr_uses_script_size(condition) || expr_uses_script_size(then_expr) || expr_uses_script_size(else_expr) } - Expr::Array(values) => values.iter().any(expr_uses_script_size), - Expr::StateObject(fields) => fields.iter().any(|field| expr_uses_script_size(&field.expr)), - Expr::Call { args, .. } => args.iter().any(expr_uses_script_size), - Expr::New { args, .. } => args.iter().any(expr_uses_script_size), - Expr::Split { source, index, .. } => expr_uses_script_size(source) || expr_uses_script_size(index), - Expr::Slice { source, start, end } => { + ExprKind::Array(values) => values.iter().any(expr_uses_script_size), + ExprKind::StateObject(fields) => fields.iter().any(|field| expr_uses_script_size(&field.expr)), + ExprKind::Call { args, .. } => args.iter().any(expr_uses_script_size), + ExprKind::New { args, .. } => args.iter().any(expr_uses_script_size), + ExprKind::Split { source, index, .. } => expr_uses_script_size(source) || expr_uses_script_size(index), + ExprKind::Slice { source, start, end, .. } => { expr_uses_script_size(source) || expr_uses_script_size(start) || expr_uses_script_size(end) } - Expr::ArrayIndex { source, index } => expr_uses_script_size(source) || expr_uses_script_size(index), - Expr::Introspection { index, .. } => expr_uses_script_size(index), - Expr::Int(_) | Expr::Bool(_) | Expr::Byte(_) | Expr::String(_) | Expr::Identifier(_) => false, - Expr::Nullary(_) => false, + ExprKind::UnarySuffix { source, .. } => expr_uses_script_size(source), + ExprKind::ArrayIndex { source, index } => expr_uses_script_size(source) || expr_uses_script_size(index), + ExprKind::Introspection { index, .. } => expr_uses_script_size(index), + ExprKind::Int(_) + | ExprKind::Bool(_) + | ExprKind::Byte(_) + | ExprKind::String(_) + | ExprKind::Identifier(_) + | ExprKind::DateLiteral(_) + | ExprKind::NumberWithUnit { .. } + | ExprKind::Nullary(_) => false, } } -// Helper to check if an expression is an array of bytes -fn is_byte_array(expr: &Expr) -> bool { - match expr { - Expr::Array(values) => values.iter().all(|v| matches!(v, Expr::Byte(_))), - _ => false, - } +fn is_byte_array<'i>(expr: &Expr<'i>) -> bool { + byte_array_len(expr).is_some() } -// Helper to get the length of a byte array -fn byte_array_len(expr: &Expr) -> Option { - match expr { - Expr::Array(values) if values.iter().all(|v| matches!(v, Expr::Byte(_))) => Some(values.len()), +fn byte_array_len<'i>(expr: &Expr<'i>) -> Option { + match &expr.kind { + ExprKind::Array(values) if values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))) => Some(values.len()), _ => None, } } -fn expr_matches_type_ref(expr: &Expr, type_ref: &TypeRef) -> bool { +/// Does the expression match the expected type passed as a secondary argument. +/// +/// If type is a fixed-size array (known at parsing time), it also verifies the array length. +fn expr_matches_type_ref<'i>(expr: &Expr<'i>, type_ref: &TypeRef) -> bool { if is_array_type_ref(type_ref) { - // Check for fixed-size array type[N] if let Some(size) = array_size_ref(type_ref) { - // For fixed-size arrays like byte[4], int[3] if let Some(element_type) = array_element_type_ref(type_ref) { if element_type.base == TypeBase::Byte { - // byte[N] should match Expr::Array of Expr::Byte with exact length N return byte_array_len(expr) == Some(size); } - // For other fixed-size arrays, match array literal - return matches!(expr, Expr::Array(values) if values.len() == size && array_literal_matches_type_ref(values, type_ref)); + return matches!(&expr.kind, ExprKind::Array(values) if values.len() == size && array_literal_matches_type_ref(values, type_ref)); } } - // Dynamic arrays type[] - return is_byte_array(expr) || matches!(expr, Expr::Array(values) if array_literal_matches_type_ref(values, type_ref)); + return is_byte_array(expr) + || matches!(&expr.kind, ExprKind::Array(values) if array_literal_matches_type_ref(values, type_ref)); } + match type_ref.base { - TypeBase::Int => matches!(expr, Expr::Int(_)), - TypeBase::Bool => matches!(expr, Expr::Bool(_)), - TypeBase::String => matches!(expr, Expr::String(_)), - TypeBase::Byte => matches!(expr, Expr::Byte(_)), + TypeBase::Int => matches!(&expr.kind, ExprKind::Int(_) | ExprKind::DateLiteral(_)), + TypeBase::Bool => matches!(&expr.kind, ExprKind::Bool(_)), + TypeBase::String => matches!(&expr.kind, ExprKind::String(_)), + TypeBase::Byte => matches!(&expr.kind, ExprKind::Byte(_)), TypeBase::Pubkey => byte_array_len(expr) == Some(32), TypeBase::Sig => byte_array_len(expr) == Some(65), TypeBase::Datasig => byte_array_len(expr) == Some(64), } } -fn array_literal_matches_type_ref(values: &[Expr], type_ref: &TypeRef) -> bool { +fn array_literal_matches_type_ref<'i>(values: &[Expr<'i>], type_ref: &TypeRef) -> bool { let Some(element_type) = array_element_type_ref(type_ref) else { return false; }; - // Check if this is a fixed-size array if let Some(expected_size) = array_size_ref(type_ref) { if values.len() != expected_size { return false; @@ -363,11 +351,11 @@ fn array_literal_matches_type_ref(values: &[Expr], type_ref: &TypeRef) -> bool { values.iter().all(|value| expr_matches_type_ref(value, &element_type)) } -fn array_literal_matches_type_with_env_ref( - values: &[Expr], +fn array_literal_matches_type_with_env_ref<'i>( + values: &[Expr<'i>], type_ref: &TypeRef, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { let Some(element_type) = array_element_type_ref(type_ref) else { return false; @@ -379,8 +367,8 @@ fn array_literal_matches_type_with_env_ref( } } - values.iter().all(|value| match value { - Expr::Identifier(name) => types + values.iter().all(|value| match &value.kind { + ExprKind::Identifier(name) => types .get(name) .and_then(|value_type| parse_type_ref(value_type).ok()) .is_some_and(|value_type| is_type_assignable_ref(&value_type, &element_type, constants)), @@ -388,7 +376,7 @@ fn array_literal_matches_type_with_env_ref( }) } -fn build_function_abi(contract: &ContractAst) -> FunctionAbi { +fn build_function_abi_entries<'i>(contract: &ContractAst<'i>) -> Vec { contract .functions .iter() @@ -423,11 +411,11 @@ fn array_size_ref(type_ref: &TypeRef) -> Option { } } -fn array_size_with_constants_ref(type_ref: &TypeRef, constants: &HashMap) -> Option { +fn array_size_with_constants_ref<'i>(type_ref: &TypeRef, constants: &HashMap>) -> Option { match type_ref.array_size()? { ArrayDim::Fixed(size) => Some(*size), ArrayDim::Constant(name) => { - if let Some(Expr::Int(value)) = constants.get(name) { + if let Some(Expr { kind: ExprKind::Int(value), .. }) = constants.get(name) { if *value >= 0 { return Some(*value as usize); } @@ -466,7 +454,7 @@ fn array_element_size_ref(type_ref: &TypeRef) -> Option { array_element_type_ref(type_ref).and_then(|element| fixed_type_size_ref(&element)) } -fn contains_return(stmt: &Statement) -> bool { +fn contains_return(stmt: &Statement<'_>) -> bool { match stmt { Statement::Return { .. } => true, Statement::If { then_branch, else_branch, .. } => { @@ -477,7 +465,7 @@ fn contains_return(stmt: &Statement) -> bool { } } -fn contains_yield(stmt: &Statement) -> bool { +fn contains_yield(stmt: &Statement<'_>) -> bool { match stmt { Statement::Yield { .. } => true, Statement::If { then_branch, else_branch, .. } => { @@ -488,11 +476,11 @@ fn contains_yield(stmt: &Statement) -> bool { } } -fn validate_return_types( - exprs: &[Expr], +fn validate_return_types<'i>( + exprs: &[Expr<'i>], return_types: &[TypeRef], types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> Result<(), CompilerError> { if return_types.is_empty() { return Err(CompilerError::Unsupported("return requires function return types".to_string())); @@ -513,7 +501,7 @@ fn has_explicit_array_size_ref(type_ref: &TypeRef) -> bool { !matches!(type_ref.array_size(), Some(ArrayDim::Dynamic) | None) } -fn is_array_type_assignable_ref(actual: &TypeRef, expected: &TypeRef, constants: &HashMap) -> bool { +fn is_array_type_assignable_ref<'i>(actual: &TypeRef, expected: &TypeRef, constants: &HashMap>) -> bool { if actual == expected { return true; } @@ -536,46 +524,48 @@ fn is_array_type_assignable_ref(actual: &TypeRef, expected: &TypeRef, constants: } } -fn is_type_assignable_ref(actual: &TypeRef, expected: &TypeRef, constants: &HashMap) -> bool { +fn is_type_assignable_ref<'i>(actual: &TypeRef, expected: &TypeRef, constants: &HashMap>) -> bool { actual == expected || is_array_type_assignable_ref(actual, expected, constants) } -fn expr_matches_type_with_env_ref( - expr: &Expr, +fn expr_matches_type_with_env_ref<'i>( + expr: &Expr<'i>, type_ref: &TypeRef, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { - match expr { - Expr::Identifier(name) => { + match &expr.kind { + ExprKind::Identifier(name) => { types.get(name).and_then(|t| parse_type_ref(t).ok()).is_some_and(|t| is_type_assignable_ref(&t, type_ref, constants)) } - Expr::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), + ExprKind::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), _ => expr_matches_type_ref(expr, type_ref), } } -fn expr_matches_return_type_ref( - expr: &Expr, +fn expr_matches_return_type_ref<'i>( + expr: &Expr<'i>, type_ref: &TypeRef, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { - match expr { - Expr::Identifier(name) => { + match &expr.kind { + ExprKind::Identifier(name) => { types.get(name).and_then(|t| parse_type_ref(t).ok()).is_some_and(|t| is_type_assignable_ref(&t, type_ref, constants)) } - Expr::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), - Expr::Int(_) | Expr::Bool(_) | Expr::Byte(_) | Expr::String(_) => expr_matches_type_ref(expr, type_ref), + ExprKind::Array(values) => is_array_type_ref(type_ref) && array_literal_matches_type_ref(values, type_ref), + ExprKind::Int(_) | ExprKind::DateLiteral(_) | ExprKind::Bool(_) | ExprKind::Byte(_) | ExprKind::String(_) => { + expr_matches_type_ref(expr, type_ref) + } _ => true, } } -fn infer_fixed_array_type_from_initializer_ref( +fn infer_fixed_array_type_from_initializer_ref<'i>( declared_type: &TypeRef, - initializer: Option<&Expr>, + initializer: Option<&Expr<'i>>, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> Option { if !declared_type.array_size().is_some_and(|dim| matches!(dim, ArrayDim::Dynamic)) { return None; @@ -584,13 +574,13 @@ fn infer_fixed_array_type_from_initializer_ref( let element_type = array_element_type_ref(declared_type)?; let init = initializer?; - match init { - Expr::Array(values) => { + match &init.kind { + ExprKind::Array(values) => { let mut inferred = element_type.clone(); inferred.array_dims.push(ArrayDim::Fixed(values.len())); if array_literal_matches_type_with_env_ref(values, &inferred, types, constants) { Some(inferred) } else { None } } - Expr::Identifier(name) => { + ExprKind::Identifier(name) => { let other_type = parse_type_ref(types.get(name)?).ok()?; if !is_array_type_ref(&other_type) || array_element_type_ref(&other_type) != Some(element_type.clone()) { return None; @@ -604,15 +594,15 @@ fn infer_fixed_array_type_from_initializer_ref( } } -fn expr_matches_type(expr: &Expr, type_name: &str) -> bool { +fn expr_matches_type<'i>(expr: &Expr<'i>, type_name: &str) -> bool { parse_type_ref(type_name).is_ok_and(|type_ref| expr_matches_type_ref(expr, &type_ref)) } -fn array_literal_matches_type_with_env( - values: &[Expr], +fn array_literal_matches_type_with_env<'i>( + values: &[Expr<'i>], type_name: &str, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { parse_type_ref(type_name).is_ok_and(|type_ref| array_literal_matches_type_with_env_ref(values, &type_ref, types, constants)) } @@ -632,7 +622,7 @@ fn array_size(type_name: &str) -> Option { array_size_ref(&type_ref) } -fn array_size_with_constants(type_name: &str, constants: &HashMap) -> Option { +fn array_size_with_constants<'i>(type_name: &str, constants: &HashMap>) -> Option { let type_ref = parse_type_ref(type_name).ok()?; array_size_with_constants_ref(&type_ref, constants) } @@ -647,7 +637,7 @@ fn array_element_size(type_name: &str) -> Option { array_element_size_ref(&type_ref) } -fn is_type_assignable(actual: &str, expected: &str, constants: &HashMap) -> bool { +fn is_type_assignable<'i>(actual: &str, expected: &str, constants: &HashMap>) -> bool { let Ok(actual_type) = parse_type_ref(actual) else { return false; }; @@ -657,27 +647,27 @@ fn is_type_assignable(actual: &str, expected: &str, constants: &HashMap( + expr: &Expr<'i>, type_name: &str, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> bool { parse_type_ref(type_name).is_ok_and(|type_ref| expr_matches_type_with_env_ref(expr, &type_ref, types, constants)) } -fn infer_fixed_array_type_from_initializer( +fn infer_fixed_array_type_from_initializer<'i>( declared_type: &str, - initializer: Option<&Expr>, + initializer: Option<&Expr<'i>>, types: &HashMap, - constants: &HashMap, + constants: &HashMap>, ) -> Option { let declared_type = parse_type_ref(declared_type).ok()?; infer_fixed_array_type_from_initializer_ref(&declared_type, initializer, types, constants).map(|t| type_name_from_ref(&t)) } -impl CompiledContract { - pub fn build_sig_script(&self, function_name: &str, args: Vec) -> Result, CompilerError> { +impl<'i> CompiledContract<'i> { + pub fn build_sig_script(&self, function_name: &str, args: Vec>) -> Result, CompilerError> { let function = self .abi .iter() @@ -701,17 +691,17 @@ impl CompiledContract { let mut builder = ScriptBuilder::new(); for (input, arg) in function.inputs.iter().zip(args) { if is_array_type(&input.type_name) { - match arg { - Expr::Array(ref values) => { - // Check if it's a byte array or other array type + let kind = arg.kind.clone(); + match kind { + ExprKind::Array(values) => { if is_byte_array(&arg) { - // Extract bytes from Expr::Byte array - let bytes: Vec = - values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); + let bytes: Vec = values + .iter() + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) + .collect(); builder.add_data(&bytes)?; } else { - // Regular array - encode it - let bytes = encode_array_literal(values, &input.type_name)?; + let bytes = encode_array_literal(&values, &input.type_name)?; builder.add_data(&bytes)?; } } @@ -734,22 +724,28 @@ impl CompiledContract { } } -fn push_sigscript_arg(builder: &mut ScriptBuilder, arg: Expr) -> Result<(), CompilerError> { - match arg { - Expr::Int(value) => { +fn push_sigscript_arg<'i>(builder: &mut ScriptBuilder, arg: Expr<'i>) -> Result<(), CompilerError> { + match arg.kind { + ExprKind::Int(value) => { builder.add_i64(value)?; } - Expr::Bool(value) => { + ExprKind::Bool(value) => { builder.add_i64(if value { 1 } else { 0 })?; } - Expr::String(value) => { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; } - Expr::Array(values) if is_byte_array(&Expr::Array(values.clone())) => { - // Handle byte arrays - let bytes: Vec = values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); + ExprKind::Byte(value) => { + builder.add_data(&[value])?; + } + ExprKind::Array(values) if values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))) => { + let bytes: Vec = + values.iter().filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }).collect(); builder.add_data(&bytes)?; } + ExprKind::DateLiteral(value) => { + builder.add_i64(value)?; + } _ => { return Err(CompilerError::Unsupported("signature script arguments must be literals".to_string())); } @@ -757,22 +753,23 @@ fn push_sigscript_arg(builder: &mut ScriptBuilder, arg: Expr) -> Result<(), Comp Ok(()) } -fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, CompilerError> { +fn encode_fixed_size_value<'i>(value: &Expr<'i>, type_name: &str) -> Result, CompilerError> { match type_name { "int" => { - let Expr::Int(number) = value else { - return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); + let number = match &value.kind { + ExprKind::Int(number) | ExprKind::DateLiteral(number) => *number, + _ => return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())), }; Ok(number.to_le_bytes().to_vec()) } "bool" => { - let Expr::Bool(flag) = value else { + let ExprKind::Bool(flag) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; Ok(vec![u8::from(*flag)]) } "byte" => { - let Expr::Byte(byte) = value else { + let ExprKind::Byte(byte) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; Ok(vec![*byte]) @@ -784,10 +781,13 @@ fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, Com if len != 32 { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); } - let Expr::Array(bytes_exprs) = value else { + let ExprKind::Array(bytes_exprs) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; - Ok(bytes_exprs.iter().filter_map(|value| if let Expr::Byte(byte) = value { Some(*byte) } else { None }).collect()) + Ok(bytes_exprs + .iter() + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) + .collect()) } _ => { // Handle fixed-size byte arrays like byte[N] @@ -799,18 +799,18 @@ fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, Com if len != size { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); } - let Expr::Array(bytes_exprs) = value else { + let ExprKind::Array(bytes_exprs) = &value.kind else { return Err(CompilerError::Unsupported("array literal element type mismatch".to_string())); }; return Ok(bytes_exprs .iter() - .filter_map(|value| if let Expr::Byte(byte) = value { Some(*byte) } else { None }) + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) .collect()); } } // Handle nested fixed-size arrays with known element sizes. - if let Expr::Array(values) = value { + if let ExprKind::Array(values) = &value.kind { let element_type = array_element_type(type_name) .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; let expected_len = array_size(type_name) @@ -831,7 +831,7 @@ fn encode_fixed_size_value(value: &Expr, type_name: &str) -> Result, Com } } -fn encode_array_literal(values: &[Expr], type_name: &str) -> Result, CompilerError> { +fn encode_array_literal<'i>(values: &[Expr<'i>], type_name: &str) -> Result, CompilerError> { let element_type = array_element_type(type_name) .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; let mut out = Vec::new(); @@ -844,13 +844,13 @@ fn encode_array_literal(values: &[Expr], type_name: &str) -> Result, Com Ok(out) } -fn infer_fixed_type_from_literal_expr(expr: &Expr) -> Option { - match expr { - Expr::Int(_) => Some("int".to_string()), - Expr::Bool(_) => Some("bool".to_string()), - Expr::Byte(_) => Some("byte".to_string()), - Expr::Array(values) if is_byte_array(expr) => Some(format!("byte[{}]", values.len())), - Expr::Array(values) => { +fn infer_fixed_type_from_literal_expr<'i>(expr: &Expr<'i>) -> Option { + match &expr.kind { + ExprKind::Int(_) | ExprKind::DateLiteral(_) => Some("int".to_string()), + ExprKind::Bool(_) => Some("bool".to_string()), + ExprKind::Byte(_) => Some("byte".to_string()), + ExprKind::Array(values) if is_byte_array(expr) => Some(format!("byte[{}]", values.len())), + ExprKind::Array(values) => { let nested_type = infer_fixed_array_literal_type(values)?; Some(nested_type.trim_end_matches("[]").to_string()) } @@ -858,7 +858,7 @@ fn infer_fixed_type_from_literal_expr(expr: &Expr) -> Option { } } -fn infer_fixed_array_literal_type(values: &[Expr]) -> Option { +fn infer_fixed_array_literal_type<'i>(values: &[Expr<'i>]) -> Option { if values.is_empty() { return None; } @@ -871,7 +871,7 @@ fn infer_fixed_array_literal_type(values: &[Expr]) -> Option { } } -pub fn function_branch_index(contract: &ContractAst, function_name: &str) -> Result { +pub fn function_branch_index<'i>(contract: &ContractAst<'i>, function_name: &str) -> Result { contract .functions .iter() @@ -881,14 +881,14 @@ pub fn function_branch_index(contract: &ContractAst, function_name: &str) -> Res .ok_or_else(|| CompilerError::Unsupported(format!("function '{function_name}' not found"))) } -fn compile_function( - function: &FunctionAst, +fn compile_function<'i>( + function: &FunctionAst<'i>, function_index: usize, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - constants: &HashMap, + constants: &HashMap>, options: CompileOptions, - functions: &HashMap, + functions: &HashMap>, function_order: &HashMap, script_size: Option, ) -> Result<(String, Vec), CompilerError> { @@ -923,7 +923,7 @@ fn compile_function( return Err(CompilerError::Unsupported(format!("array element type must have known size: {return_type_name}"))); } } - let mut env: HashMap = constants.clone(); + let mut env: HashMap> = constants.clone(); let mut builder = ScriptBuilder::new(); let mut yields: Vec = Vec::new(); @@ -953,14 +953,13 @@ fn compile_function( let body_len = function.body.len(); for (index, stmt) in function.body.iter().enumerate() { - if matches!(stmt, Statement::Return { .. }) { + if let Statement::Return { exprs, .. } = stmt { if index != body_len - 1 { return Err(CompilerError::Unsupported("return statement must be the last statement".to_string())); } - let Statement::Return { exprs } = stmt else { unreachable!() }; validate_return_types(exprs, &function.return_types, &types, constants)?; for expr in exprs { - let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new())?; + let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new()).map_err(|err| err.with_span(&expr.span))?; yields.push(resolved); } continue; @@ -980,7 +979,8 @@ fn compile_function( function_index, &mut yields, script_size, - )?; + ) + .map_err(|err| err.with_span(&stmt.span()))?; } let yield_count = yields.len(); @@ -1023,20 +1023,20 @@ fn compile_function( } #[allow(clippy::too_many_arguments)] -fn compile_statement( - stmt: &Statement, - env: &mut HashMap, +fn compile_statement<'i>( + stmt: &Statement<'i>, + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, ) -> Result<(), CompilerError> { match stmt { @@ -1065,9 +1065,9 @@ fn compile_statement( let is_byte_array_type = effective_type_name.starts_with("byte[") && effective_type_name.ends_with("[]"); let initial = match expr { - Some(Expr::Identifier(other)) => match types.get(other) { + Some(Expr { kind: ExprKind::Identifier(other), .. }) => match types.get(other) { Some(other_type) if is_type_assignable(other_type, &effective_type_name, contract_constants) => { - Expr::Identifier(other.clone()) + Expr::new(ExprKind::Identifier(other.clone()), span::Span::default()) } Some(_) => { return Err(CompilerError::Unsupported("array assignment requires compatible array types".to_string())); @@ -1078,14 +1078,14 @@ fn compile_statement( // byte[] can be initialized from any bytes expression e.clone() } - Some(Expr::Array(values)) => { + Some(e @ Expr { kind: ExprKind::Array(values), .. }) => { if !array_literal_matches_type_with_env(values, &effective_type_name, types, contract_constants) { return Err(CompilerError::Unsupported("array initializer must be another array".to_string())); } - resolve_expr(Expr::Array(values.clone()), env, &mut HashSet::new())? + resolve_expr(Expr::new(ExprKind::Array(values.clone()), e.span), env, &mut HashSet::new())? } Some(_) => return Err(CompilerError::Unsupported("array initializer must be another array".to_string())), - None => Expr::Array(Vec::new()), + None => Expr::new(ExprKind::Array(Vec::new()), span::Span::default()), }; env.insert(name.clone(), initial); types.insert(name.clone(), effective_type_name.clone()); @@ -1096,7 +1096,7 @@ fn compile_statement( expr.clone().ok_or_else(|| CompilerError::Unsupported("variable definition requires initializer".to_string()))?; // For array literals, validate that the size matches the declared type - if let Expr::Array(values) = &expr { + if let ExprKind::Array(values) = &expr.kind { if let Some(expected_size) = array_size_with_constants(&effective_type_name, contract_constants) { if values.len() != expected_size { return Err(CompilerError::Unsupported(format!( @@ -1117,7 +1117,8 @@ fn compile_statement( } } - let stored_expr = if matches!(expr, Expr::Array(_)) { resolve_expr(expr, env, &mut HashSet::new())? } else { expr }; + let stored_expr = + if matches!(&expr.kind, ExprKind::Array(_)) { resolve_expr(expr, env, &mut HashSet::new())? } else { expr }; env.insert(name.clone(), stored_expr); types.insert(name.clone(), effective_type_name.clone()); Ok(()) @@ -1129,7 +1130,7 @@ fn compile_statement( Ok(()) } } - Statement::ArrayPush { name, expr } => { + Statement::ArrayPush { name, expr, .. } => { let array_type = types.get(name).ok_or_else(|| CompilerError::UndefinedIdentifier(name.clone()))?; if !is_array_type(array_type) { return Err(CompilerError::Unsupported("push() only supported on arrays".to_string())); @@ -1139,9 +1140,15 @@ fn compile_statement( let _element_size = array_element_size(array_type) .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; let element_expr = if element_type == "int" { - Expr::Call { name: "byte[8]".to_string(), args: vec![expr.clone()] } + Expr::new( + ExprKind::Call { name: "byte[8]".to_string(), args: vec![expr.clone()], name_span: span::Span::default() }, + span::Span::default(), + ) } else if element_type == "byte" { - Expr::Call { name: "byte[1]".to_string(), args: vec![expr.clone()] } + Expr::new( + ExprKind::Call { name: "byte[1]".to_string(), args: vec![expr.clone()], name_span: span::Span::default() }, + span::Span::default(), + ) } else if element_type.contains('[') && element_type.starts_with("byte") { // Handle byte[N] type if expr_is_bytes(expr, env, types) { @@ -1155,7 +1162,14 @@ fn compile_statement( if base_type == "byte" { if let Ok(_size) = size_str.parse::() { // Cast expression to byte[N] - Expr::Call { name: element_type.to_string(), args: vec![expr.clone()] } + Expr::new( + ExprKind::Call { + name: element_type.to_string(), + args: vec![expr.clone()], + name_span: span::Span::default(), + }, + span::Span::default(), + ) } else { return Err(CompilerError::Unsupported("invalid array size".to_string())); } @@ -1173,8 +1187,11 @@ fn compile_statement( return Err(CompilerError::Unsupported("array element type not supported".to_string())); }; - let current = env.get(name).cloned().unwrap_or_else(|| Expr::Array(Vec::new())); - let updated = Expr::Binary { op: BinaryOp::Add, left: Box::new(current), right: Box::new(element_expr) }; + let current = env.get(name).cloned().unwrap_or_else(|| Expr::new(ExprKind::Array(Vec::new()), span::Span::default())); + let updated = Expr::new( + ExprKind::Binary { op: BinaryOp::Add, left: Box::new(current), right: Box::new(element_expr) }, + span::Span::default(), + ); env.insert(name.clone(), updated); Ok(()) } @@ -1198,7 +1215,7 @@ fn compile_statement( Statement::TimeOp { tx_var, expr, .. } => { compile_time_op_statement(tx_var, expr, env, params, types, builder, options, script_size, contract_constants) } - Statement::If { condition, then_branch, else_branch } => compile_if_statement( + Statement::If { condition, then_branch, else_branch, .. } => compile_if_statement( condition, then_branch, else_branch.as_deref(), @@ -1216,7 +1233,7 @@ fn compile_statement( yields, script_size, ), - Statement::For { ident, start, end, body } => compile_for_statement( + Statement::For { ident, start, end, body, .. } => compile_for_statement( ident, start, end, @@ -1235,22 +1252,30 @@ fn compile_statement( yields, script_size, ), - Statement::Yield { expr } => { + Statement::Yield { expr, .. } => { let mut visiting = HashSet::new(); let resolved = resolve_expr(expr.clone(), env, &mut visiting)?; yields.push(resolved); Ok(()) } Statement::Return { .. } => Err(CompilerError::Unsupported("return statement must be the last statement".to_string())), - Statement::TupleAssignment { left_name, right_name, expr, .. } => match expr.clone() { - Expr::Split { source, index, .. } => { - env.insert(left_name.clone(), Expr::Split { source: source.clone(), index: index.clone(), part: SplitPart::Left }); - env.insert(right_name.clone(), Expr::Split { source, index, part: SplitPart::Right }); + Statement::TupleAssignment { left_name, right_name, expr, .. } => match &expr.kind { + ExprKind::Split { source, index, span: split_span, .. } => { + let left_expr = Expr::new( + ExprKind::Split { source: source.clone(), index: index.clone(), part: SplitPart::Left, span: *split_span }, + span::Span::default(), + ); + let right_expr = Expr::new( + ExprKind::Split { source: source.clone(), index: index.clone(), part: SplitPart::Right, span: *split_span }, + span::Span::default(), + ); + env.insert(left_name.clone(), left_expr); + env.insert(right_name.clone(), right_expr); Ok(()) } _ => Err(CompilerError::Unsupported("tuple assignment only supports split()".to_string())), }, - Statement::FunctionCall { name, args } => { + Statement::FunctionCall { name, args, .. } => { if name == "validateOutputState" { return compile_validate_output_state_statement( args, @@ -1299,7 +1324,7 @@ fn compile_statement( } Ok(()) } - Statement::StateFunctionCallAssign { bindings, name, args } => { + Statement::StateFunctionCallAssign { bindings, name, args, .. } => { if name == "readInputState" { return compile_read_input_state_statement( bindings, @@ -1316,7 +1341,7 @@ fn compile_statement( name ))) } - Statement::FunctionCallAssign { bindings, name, args } => { + Statement::FunctionCallAssign { bindings, name, args, .. } => { let function = functions.get(name).ok_or_else(|| CompilerError::Unsupported(format!("function '{}' not found", name)))?; if function.return_types.is_empty() { return Err(CompilerError::Unsupported("function has no return types".to_string())); @@ -1353,13 +1378,13 @@ fn compile_statement( } Ok(()) } - Statement::Assign { name, expr } => { + Statement::Assign { name, expr, .. } => { if let Some(type_name) = types.get(name) { if is_array_type(type_name) { - match expr { - Expr::Identifier(other) => match types.get(other) { + match &expr.kind { + ExprKind::Identifier(other) => match types.get(other) { Some(other_type) if is_type_assignable(other_type, type_name, contract_constants) => { - env.insert(name.clone(), Expr::Identifier(other.clone())); + env.insert(name.clone(), Expr::new(ExprKind::Identifier(other.clone()), span::Span::default())); return Ok(()); } Some(_) => { @@ -1369,7 +1394,9 @@ fn compile_statement( } None => return Err(CompilerError::UndefinedIdentifier(other.clone())), }, - _ => return Err(CompilerError::Unsupported("array assignment only supports array identifiers".to_string())), + _ => { + return Err(CompilerError::Unsupported("array assignment only supports array identifiers".to_string())); + } } } } @@ -1382,7 +1409,10 @@ fn compile_statement( } } -fn encoded_field_chunk_size(field: &ContractFieldAst, contract_constants: &HashMap) -> Result { +fn encoded_field_chunk_size<'i>( + field: &ContractFieldAst<'i>, + contract_constants: &HashMap>, +) -> Result { if field.type_ref.array_dims.is_empty() && field.type_ref.base == TypeBase::Int { return Ok(10); } @@ -1405,13 +1435,13 @@ fn encoded_field_chunk_size(field: &ContractFieldAst, contract_constants: &HashM Ok(data_prefix(payload_size).len() + payload_size) } -fn read_input_state_binding_expr( - input_idx: &Expr, - field: &ContractFieldAst, +fn read_input_state_binding_expr<'i>( + input_idx: &Expr<'i>, + field: &ContractFieldAst<'i>, field_chunk_offset: usize, script_size_value: i64, - contract_constants: &HashMap, -) -> Result { + contract_constants: &HashMap>, +) -> Result, CompilerError> { let (field_payload_offset, field_payload_len, decode_int) = if field.type_ref.array_dims.is_empty() && field.type_ref.base == TypeBase::Int { (field_chunk_offset + 1, 8usize, true) @@ -1434,26 +1464,35 @@ fn read_input_state_binding_expr( ))); }; - let sig_len = Expr::Call { name: "OpTxInputScriptSigLen".to_string(), args: vec![input_idx.clone()] }; - let start = Expr::Binary { - op: BinaryOp::Add, - left: Box::new(Expr::Binary { op: BinaryOp::Sub, left: Box::new(sig_len), right: Box::new(Expr::Int(script_size_value)) }), - right: Box::new(Expr::Int(field_payload_offset as i64)), - }; - let end = Expr::Binary { op: BinaryOp::Add, left: Box::new(start.clone()), right: Box::new(Expr::Int(field_payload_len as i64)) }; - let substr = Expr::Call { name: "OpTxInputScriptSigSubstr".to_string(), args: vec![input_idx.clone(), start, end] }; + let sig_len = Expr::call("OpTxInputScriptSigLen", vec![input_idx.clone()]); + let start = Expr::new( + ExprKind::Binary { + op: BinaryOp::Add, + left: Box::new(Expr::new( + ExprKind::Binary { op: BinaryOp::Sub, left: Box::new(sig_len), right: Box::new(Expr::int(script_size_value)) }, + span::Span::default(), + )), + right: Box::new(Expr::int(field_payload_offset as i64)), + }, + span::Span::default(), + ); + let end = Expr::new( + ExprKind::Binary { op: BinaryOp::Add, left: Box::new(start.clone()), right: Box::new(Expr::int(field_payload_len as i64)) }, + span::Span::default(), + ); + let substr = Expr::call("OpTxInputScriptSigSubstr", vec![input_idx.clone(), start, end]); - if decode_int { Ok(Expr::Call { name: "OpBin2Num".to_string(), args: vec![substr] }) } else { Ok(substr) } + if decode_int { Ok(Expr::call("OpBin2Num", vec![substr])) } else { Ok(substr) } } -fn compile_read_input_state_statement( - bindings: &[StateBindingAst], - args: &[Expr], - env: &mut HashMap, +fn compile_read_input_state_statement<'i>( + bindings: &[StateBindingAst<'i>], + args: &[Expr<'i>], + env: &mut HashMap>, types: &mut HashMap, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { if args.len() != 1 { return Err(CompilerError::Unsupported("readInputState(input_idx) expects 1 argument".to_string())); @@ -1464,7 +1503,7 @@ fn compile_read_input_state_statement( let script_size_value = script_size.ok_or_else(|| CompilerError::Unsupported("readInputState requires this.scriptSize".to_string()))?; - let mut bindings_by_field: HashMap<&str, &StateBindingAst> = HashMap::new(); + let mut bindings_by_field: HashMap<&str, &StateBindingAst<'i>> = HashMap::new(); for binding in bindings { if bindings_by_field.insert(binding.field_name.as_str(), binding).is_some() { return Err(CompilerError::Unsupported(format!("duplicate state field '{}'", binding.field_name))); @@ -1501,16 +1540,16 @@ fn compile_read_input_state_statement( #[allow(clippy::too_many_arguments)] fn compile_validate_output_state_statement( - args: &[Expr], - env: &HashMap, + args: &[Expr<'_>], + env: &HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'_>], contract_field_prefix_len: usize, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { if args.len() != 2 { return Err(CompilerError::Unsupported("validateOutputState(output_idx, new_state) expects 2 arguments".to_string())); @@ -1520,7 +1559,7 @@ fn compile_validate_output_state_statement( } let output_idx = &args[0]; - let Expr::StateObject(state_entries) = &args[1] else { + let ExprKind::StateObject(state_entries) = &args[1].kind else { return Err(CompilerError::Unsupported("validateOutputState second argument must be an object literal".to_string())); }; @@ -1672,19 +1711,19 @@ fn compile_validate_output_state_statement( } #[allow(clippy::too_many_arguments)] -fn compile_inline_call( +fn compile_inline_call<'i>( name: &str, - args: &[Expr], + args: &[Expr<'i>], caller_types: &mut HashMap, - caller_env: &mut HashMap, + caller_env: &mut HashMap>, builder: &mut ScriptBuilder, options: CompileOptions, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, caller_index: usize, script_size: Option, -) -> Result, CompilerError> { +) -> Result>, CompilerError> { let function = functions.get(name).ok_or_else(|| CompilerError::Unsupported(format!("function '{}' not found", name)))?; let callee_index = function_order.get(name).copied().ok_or_else(|| CompilerError::Unsupported(format!("function '{}' not found", name)))?; @@ -1711,14 +1750,14 @@ fn compile_inline_call( } } - let mut env: HashMap = contract_constants.clone(); + let mut env: HashMap> = contract_constants.clone(); for (index, (param, arg)) in function.params.iter().zip(args.iter()).enumerate() { let resolved = resolve_expr(arg.clone(), caller_env, &mut HashSet::new())?; let temp_name = format!("__arg_{name}_{index}"); let param_type_name = type_name_from_ref(¶m.type_ref); env.insert(temp_name.clone(), resolved.clone()); types.insert(temp_name.clone(), param_type_name.clone()); - env.insert(param.name.clone(), Expr::Identifier(temp_name.clone())); + env.insert(param.name.clone(), Expr::new(ExprKind::Identifier(temp_name.clone()), span::Span::default())); caller_env.insert(temp_name.clone(), resolved); caller_types.insert(temp_name, param_type_name); } @@ -1744,18 +1783,18 @@ fn compile_inline_call( } } - let mut yields: Vec = Vec::new(); + let mut yields: Vec> = Vec::new(); let params = HashMap::new(); let body_len = function.body.len(); for (index, stmt) in function.body.iter().enumerate() { - if matches!(stmt, Statement::Return { .. }) { + if let Statement::Return { exprs, .. } = stmt { if index != body_len - 1 { return Err(CompilerError::Unsupported("return statement must be the last statement".to_string())); } - let Statement::Return { exprs } = stmt else { unreachable!() }; - validate_return_types(exprs, &function.return_types, &types, contract_constants)?; + validate_return_types(exprs, &function.return_types, &types, contract_constants) + .map_err(|err| err.with_span(&stmt.span()))?; for expr in exprs { - let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new())?; + let resolved = resolve_expr(expr.clone(), &env, &mut HashSet::new()).map_err(|err| err.with_span(&expr.span))?; yields.push(resolved); } continue; @@ -1775,7 +1814,8 @@ fn compile_inline_call( callee_index, &mut yields, script_size, - )?; + ) + .map_err(|err| err.with_span(&stmt.span()))?; } for (name, value) in env.iter() { @@ -1791,22 +1831,22 @@ fn compile_inline_call( } #[allow(clippy::too_many_arguments)] -fn compile_if_statement( - condition: &Expr, - then_branch: &[Statement], - else_branch: Option<&[Statement]>, - env: &mut HashMap, +fn compile_if_statement<'i>( + condition: &Expr<'i>, + then_branch: &[Statement<'i>], + else_branch: Option<&[Statement<'i>]>, + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, ) -> Result<(), CompilerError> { let mut stack_depth = 0i64; @@ -1873,12 +1913,12 @@ fn compile_if_statement( Ok(()) } -fn merge_env_after_if( - env: &mut HashMap, - original_env: &HashMap, - then_env: &HashMap, - else_env: &HashMap, - condition: &Expr, +fn merge_env_after_if<'i>( + env: &mut HashMap>, + original_env: &HashMap>, + then_env: &HashMap>, + else_env: &HashMap>, + condition: &Expr<'i>, ) { for (name, original_expr) in original_env { let then_expr = then_env.get(name).unwrap_or(original_expr); @@ -1889,26 +1929,29 @@ fn merge_env_after_if( } else { env.insert( name.clone(), - Expr::IfElse { - condition: Box::new(condition.clone()), - then_expr: Box::new(then_expr.clone()), - else_expr: Box::new(else_expr.clone()), - }, + Expr::new( + ExprKind::IfElse { + condition: Box::new(condition.clone()), + then_expr: Box::new(then_expr.clone()), + else_expr: Box::new(else_expr.clone()), + }, + span::Span::default(), + ), ); } } } -fn compile_time_op_statement( +fn compile_time_op_statement<'i>( tx_var: &TimeVar, - expr: &Expr, - env: &mut HashMap, + expr: &Expr<'i>, + env: &mut HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, options: CompileOptions, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { let mut stack_depth = 0i64; compile_expr(expr, env, params, types, builder, options, &mut HashSet::new(), &mut stack_depth, script_size, contract_constants)?; @@ -1926,20 +1969,20 @@ fn compile_time_op_statement( } #[allow(clippy::too_many_arguments)] -fn compile_block( - statements: &[Statement], - env: &mut HashMap, +fn compile_block<'i>( + statements: &[Statement<'i>], + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, ) -> Result<(), CompilerError> { for stmt in statements { @@ -1958,29 +2001,30 @@ fn compile_block( function_index, yields, script_size, - )?; + ) + .map_err(|err| err.with_span(&stmt.span()))?; } Ok(()) } #[allow(clippy::too_many_arguments)] -fn compile_for_statement( +fn compile_for_statement<'i>( ident: &str, - start_expr: &Expr, - end_expr: &Expr, - body: &[Statement], - env: &mut HashMap, + start_expr: &Expr<'i>, + end_expr: &Expr<'i>, + body: &[Statement<'i>], + env: &mut HashMap>, params: &HashMap, types: &mut HashMap, builder: &mut ScriptBuilder, options: CompileOptions, - contract_fields: &[ContractFieldAst], + contract_fields: &[ContractFieldAst<'i>], contract_field_prefix_len: usize, - contract_constants: &HashMap, - functions: &HashMap, + contract_constants: &HashMap>, + functions: &HashMap>, function_order: &HashMap, function_index: usize, - yields: &mut Vec, + yields: &mut Vec>, script_size: Option, ) -> Result<(), CompilerError> { let start = eval_const_int(start_expr, contract_constants)?; @@ -1992,7 +2036,7 @@ fn compile_for_statement( let name = ident.to_string(); let previous = env.get(&name).cloned(); for value in start..end { - env.insert(name.clone(), Expr::Int(value)); + env.insert(name.clone(), Expr::int(value)); compile_block( body, env, @@ -2023,16 +2067,17 @@ fn compile_for_statement( Ok(()) } -fn eval_const_int(expr: &Expr, constants: &HashMap) -> Result { - match expr { - Expr::Int(value) => Ok(*value), - Expr::Identifier(name) => match constants.get(name) { +fn eval_const_int<'i>(expr: &Expr<'i>, constants: &HashMap>) -> Result { + match &expr.kind { + ExprKind::Int(value) => Ok(*value), + ExprKind::DateLiteral(value) => Ok(*value), + ExprKind::Identifier(name) => match constants.get(name) { Some(value) => eval_const_int(value, constants), None => Err(CompilerError::Unsupported("for loop bounds must be constant integers".to_string())), }, - Expr::Unary { op: UnaryOp::Neg, expr } => Ok(-eval_const_int(expr, constants)?), - Expr::Unary { .. } => Err(CompilerError::Unsupported("for loop bounds must be constant integers".to_string())), - Expr::Binary { op, left, right } => { + ExprKind::Unary { op: UnaryOp::Neg, expr } => Ok(-eval_const_int(expr, constants)?), + ExprKind::Unary { .. } => Err(CompilerError::Unsupported("for loop bounds must be constant integers".to_string())), + ExprKind::Binary { op, left, right } => { let lhs = eval_const_int(left, constants)?; let rhs = eval_const_int(right, constants)?; match op { @@ -2058,11 +2103,16 @@ fn eval_const_int(expr: &Expr, constants: &HashMap) -> Result, visiting: &mut HashSet) -> Result { - match expr { - Expr::Identifier(name) => { +fn resolve_expr<'i>( + expr: Expr<'i>, + env: &HashMap>, + visiting: &mut HashSet, +) -> Result, CompilerError> { + let Expr { kind, span } = expr; + match kind { + ExprKind::Identifier(name) => { if name.starts_with("__arg_") { - return Ok(Expr::Identifier(name)); + return Ok(Expr::new(ExprKind::Identifier(name), span)); } if let Some(value) = env.get(&name) { if !visiting.insert(name.clone()) { @@ -2072,123 +2122,218 @@ fn resolve_expr(expr: Expr, env: &HashMap, visiting: &mut HashSet< visiting.remove(&name); Ok(resolved) } else { - Ok(Expr::Identifier(name)) - } - } - Expr::Unary { op, expr } => Ok(Expr::Unary { op, expr: Box::new(resolve_expr(*expr, env, visiting)?) }), - Expr::Binary { op, left, right } => Ok(Expr::Binary { - op, - left: Box::new(resolve_expr(*left, env, visiting)?), - right: Box::new(resolve_expr(*right, env, visiting)?), - }), - Expr::IfElse { condition, then_expr, else_expr } => Ok(Expr::IfElse { - condition: Box::new(resolve_expr(*condition, env, visiting)?), - then_expr: Box::new(resolve_expr(*then_expr, env, visiting)?), - else_expr: Box::new(resolve_expr(*else_expr, env, visiting)?), - }), - Expr::Array(values) => { + Ok(Expr::new(ExprKind::Identifier(name), span)) + } + } + ExprKind::Unary { op, expr } => { + Ok(Expr::new(ExprKind::Unary { op, expr: Box::new(resolve_expr(*expr, env, visiting)?) }, span)) + } + ExprKind::Binary { op, left, right } => Ok(Expr::new( + ExprKind::Binary { + op, + left: Box::new(resolve_expr(*left, env, visiting)?), + right: Box::new(resolve_expr(*right, env, visiting)?), + }, + span, + )), + ExprKind::IfElse { condition, then_expr, else_expr } => Ok(Expr::new( + ExprKind::IfElse { + condition: Box::new(resolve_expr(*condition, env, visiting)?), + then_expr: Box::new(resolve_expr(*then_expr, env, visiting)?), + else_expr: Box::new(resolve_expr(*else_expr, env, visiting)?), + }, + span, + )), + ExprKind::Array(values) => { let mut resolved = Vec::with_capacity(values.len()); for value in values { resolved.push(resolve_expr(value, env, visiting)?); } - Ok(Expr::Array(resolved)) + Ok(Expr::new(ExprKind::Array(resolved), span)) } - Expr::StateObject(fields) => { + ExprKind::StateObject(fields) => { let mut resolved_fields = Vec::with_capacity(fields.len()); for field in fields { - resolved_fields.push(crate::ast::StateFieldExpr { name: field.name, expr: resolve_expr(field.expr, env, visiting)? }); + resolved_fields.push(StateFieldExpr { + name: field.name, + expr: resolve_expr(field.expr, env, visiting)?, + span: field.span, + name_span: field.name_span, + }); } - Ok(Expr::StateObject(resolved_fields)) + Ok(Expr::new(ExprKind::StateObject(resolved_fields), span)) } - Expr::Call { name, args } => { + ExprKind::Call { name, args, name_span } => { let mut resolved = Vec::with_capacity(args.len()); for arg in args { resolved.push(resolve_expr(arg, env, visiting)?); } - Ok(Expr::Call { name, args: resolved }) + Ok(Expr::new(ExprKind::Call { name, args: resolved, name_span }, span)) } - Expr::New { name, args } => { + ExprKind::New { name, args, name_span } => { let mut resolved = Vec::with_capacity(args.len()); for arg in args { resolved.push(resolve_expr(arg, env, visiting)?); } - Ok(Expr::New { name, args: resolved }) - } - Expr::Split { source, index, part } => Ok(Expr::Split { - source: Box::new(resolve_expr(*source, env, visiting)?), - index: Box::new(resolve_expr(*index, env, visiting)?), - part, - }), - Expr::ArrayIndex { source, index } => Ok(Expr::ArrayIndex { - source: Box::new(resolve_expr(*source, env, visiting)?), - index: Box::new(resolve_expr(*index, env, visiting)?), - }), - Expr::Introspection { kind, index } => Ok(Expr::Introspection { kind, index: Box::new(resolve_expr(*index, env, visiting)?) }), - other => Ok(other), - } -} - -fn replace_identifier(expr: &Expr, target: &str, replacement: &Expr) -> Expr { - match expr { - Expr::Identifier(name) if name == target => replacement.clone(), - Expr::Identifier(_) => expr.clone(), - Expr::Unary { op, expr: inner } => Expr::Unary { op: *op, expr: Box::new(replace_identifier(inner, target, replacement)) }, - Expr::Binary { op, left, right } => Expr::Binary { - op: *op, - left: Box::new(replace_identifier(left, target, replacement)), - right: Box::new(replace_identifier(right, target, replacement)), - }, - Expr::Array(values) => Expr::Array(values.iter().map(|value| replace_identifier(value, target, replacement)).collect()), - Expr::StateObject(fields) => Expr::StateObject( - fields - .iter() - .map(|field| crate::ast::StateFieldExpr { - name: field.name.clone(), - expr: replace_identifier(&field.expr, target, replacement), - }) - .collect(), + Ok(Expr::new(ExprKind::New { name, args: resolved, name_span }, span)) + } + ExprKind::Split { source, index, part, span: split_span } => Ok(Expr::new( + ExprKind::Split { + source: Box::new(resolve_expr(*source, env, visiting)?), + index: Box::new(resolve_expr(*index, env, visiting)?), + part, + span: split_span, + }, + span, + )), + ExprKind::ArrayIndex { source, index } => Ok(Expr::new( + ExprKind::ArrayIndex { + source: Box::new(resolve_expr(*source, env, visiting)?), + index: Box::new(resolve_expr(*index, env, visiting)?), + }, + span, + )), + ExprKind::Introspection { kind, index, field_span } => { + Ok(Expr::new(ExprKind::Introspection { kind, index: Box::new(resolve_expr(*index, env, visiting)?), field_span }, span)) + } + ExprKind::UnarySuffix { source, kind, span: suffix_span } => Ok(Expr::new( + ExprKind::UnarySuffix { source: Box::new(resolve_expr(*source, env, visiting)?), kind, span: suffix_span }, + span, + )), + ExprKind::Slice { source, start, end, span: slice_span } => Ok(Expr::new( + ExprKind::Slice { + source: Box::new(resolve_expr(*source, env, visiting)?), + start: Box::new(resolve_expr(*start, env, visiting)?), + end: Box::new(resolve_expr(*end, env, visiting)?), + span: slice_span, + }, + span, + )), + other => Ok(Expr::new(other, span)), + } +} + +/// Replace `target` identifiers in `expr` with `replacement`. +/// +/// Example: for `x = x + 1`, this rewrites the right side to +/// ` + 1` before `resolve_expr` runs. +fn replace_identifier<'i>(expr: &Expr<'i>, target: &str, replacement: &Expr<'i>) -> Expr<'i> { + let span = expr.span; + match &expr.kind { + ExprKind::Identifier(name) if name == target => replacement.clone(), + ExprKind::Identifier(_) => expr.clone(), + ExprKind::Unary { op, expr: inner } => { + Expr::new(ExprKind::Unary { op: *op, expr: Box::new(replace_identifier(inner, target, replacement)) }, span) + } + ExprKind::Binary { op, left, right } => Expr::new( + ExprKind::Binary { + op: *op, + left: Box::new(replace_identifier(left, target, replacement)), + right: Box::new(replace_identifier(right, target, replacement)), + }, + span, ), - Expr::Call { name, args } => { - Expr::Call { name: name.clone(), args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect() } - } - Expr::New { name, args } => { - Expr::New { name: name.clone(), args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect() } - } - Expr::Split { source, index, part } => Expr::Split { - source: Box::new(replace_identifier(source, target, replacement)), - index: Box::new(replace_identifier(index, target, replacement)), - part: *part, - }, - Expr::Slice { source, start, end } => Expr::Slice { - source: Box::new(replace_identifier(source, target, replacement)), - start: Box::new(replace_identifier(start, target, replacement)), - end: Box::new(replace_identifier(end, target, replacement)), - }, - Expr::ArrayIndex { source, index } => Expr::ArrayIndex { - source: Box::new(replace_identifier(source, target, replacement)), - index: Box::new(replace_identifier(index, target, replacement)), - }, - Expr::IfElse { condition, then_expr, else_expr } => Expr::IfElse { - condition: Box::new(replace_identifier(condition, target, replacement)), - then_expr: Box::new(replace_identifier(then_expr, target, replacement)), - else_expr: Box::new(replace_identifier(else_expr, target, replacement)), - }, - Expr::Introspection { kind, index } => { - Expr::Introspection { kind: *kind, index: Box::new(replace_identifier(index, target, replacement)) } - } - Expr::Int(_) | Expr::Bool(_) | Expr::Byte(_) | Expr::String(_) | Expr::Nullary(_) => expr.clone(), + ExprKind::Array(values) => { + Expr::new(ExprKind::Array(values.iter().map(|value| replace_identifier(value, target, replacement)).collect()), span) + } + ExprKind::StateObject(fields) => Expr::new( + ExprKind::StateObject( + fields + .iter() + .map(|field| StateFieldExpr { + name: field.name.clone(), + expr: replace_identifier(&field.expr, target, replacement), + span: field.span, + name_span: field.name_span, + }) + .collect(), + ), + span, + ), + ExprKind::Call { name, args, name_span } => Expr::new( + ExprKind::Call { + name: name.clone(), + args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect(), + name_span: *name_span, + }, + span, + ), + ExprKind::New { name, args, name_span } => Expr::new( + ExprKind::New { + name: name.clone(), + args: args.iter().map(|arg| replace_identifier(arg, target, replacement)).collect(), + name_span: *name_span, + }, + span, + ), + ExprKind::Split { source, index, part, span: split_span } => Expr::new( + ExprKind::Split { + source: Box::new(replace_identifier(source, target, replacement)), + index: Box::new(replace_identifier(index, target, replacement)), + part: *part, + span: *split_span, + }, + span, + ), + ExprKind::Slice { source, start, end, span: slice_span } => Expr::new( + ExprKind::Slice { + source: Box::new(replace_identifier(source, target, replacement)), + start: Box::new(replace_identifier(start, target, replacement)), + end: Box::new(replace_identifier(end, target, replacement)), + span: *slice_span, + }, + span, + ), + ExprKind::ArrayIndex { source, index } => Expr::new( + ExprKind::ArrayIndex { + source: Box::new(replace_identifier(source, target, replacement)), + index: Box::new(replace_identifier(index, target, replacement)), + }, + span, + ), + ExprKind::IfElse { condition, then_expr, else_expr } => Expr::new( + ExprKind::IfElse { + condition: Box::new(replace_identifier(condition, target, replacement)), + then_expr: Box::new(replace_identifier(then_expr, target, replacement)), + else_expr: Box::new(replace_identifier(else_expr, target, replacement)), + }, + span, + ), + ExprKind::Introspection { kind, index, field_span } => Expr::new( + ExprKind::Introspection { + kind: *kind, + index: Box::new(replace_identifier(index, target, replacement)), + field_span: *field_span, + }, + span, + ), + ExprKind::UnarySuffix { source, kind, span: suffix_span } => Expr::new( + ExprKind::UnarySuffix { + source: Box::new(replace_identifier(source, target, replacement)), + kind: *kind, + span: *suffix_span, + }, + span, + ), + ExprKind::Int(_) + | ExprKind::Bool(_) + | ExprKind::Byte(_) + | ExprKind::String(_) + | ExprKind::DateLiteral(_) + | ExprKind::NumberWithUnit { .. } + | ExprKind::Nullary(_) => expr.clone(), } } -struct CompilationScope<'a> { - env: &'a HashMap, +struct CompilationScope<'a, 'i> { + env: &'a HashMap>, params: &'a HashMap, types: &'a HashMap, } -fn compile_expr( - expr: &Expr, - env: &HashMap, +fn compile_expr<'i>( + expr: &Expr<'i>, + env: &HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, @@ -2196,63 +2341,61 @@ fn compile_expr( visiting: &mut HashSet, stack_depth: &mut i64, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { let scope = CompilationScope { env, params, types }; - match expr { - Expr::Int(value) => { + match &expr.kind { + ExprKind::Int(value) => { builder.add_i64(*value)?; *stack_depth += 1; Ok(()) } - Expr::Bool(value) => { + ExprKind::Bool(value) => { builder.add_op(if *value { OpTrue } else { OpFalse })?; *stack_depth += 1; Ok(()) } - Expr::Byte(b) => { - builder.add_data(&[*b])?; - *stack_depth += 1; - Ok(()) - } - Expr::Array(values) if is_byte_array(&Expr::Array(values.clone())) => { - // Handle byte arrays - let bytes: Vec = values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); - builder.add_data(&bytes)?; + ExprKind::Byte(byte) => { + builder.add_data(&[*byte])?; *stack_depth += 1; Ok(()) } - Expr::Array(values) => { - if let Some(array_type) = infer_fixed_array_literal_type(values) { - let encoded = encode_array_literal(values, &array_type)?; - builder.add_data(&encoded)?; + ExprKind::Array(values) => { + // TODO: this particular handling should be done in encode_array_literal to unify the behavior + if values.is_empty() { + builder.add_data(&[])?; *stack_depth += 1; return Ok(()); } - Err(CompilerError::Unsupported( - "array literals are only supported for fixed-size element arrays and in LockingBytecodeNullData".to_string(), - )) + let inferred_type = infer_fixed_array_literal_type(values) + .ok_or_else(|| CompilerError::Unsupported("array literal type cannot be inferred".to_string()))?; + let encoded = encode_array_literal(values, &inferred_type)?; + builder.add_data(&encoded)?; + *stack_depth += 1; + Ok(()) } - Expr::StateObject(_) => { - Err(CompilerError::Unsupported("state object literals are only supported in validateOutputState()".to_string())) + ExprKind::StateObject(_) => { + Err(CompilerError::Unsupported("state object literals are only supported in validateOutputState".to_string())) } - Expr::String(value) => { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; *stack_depth += 1; Ok(()) } - Expr::Identifier(name) => { + ExprKind::Identifier(name) => { if !visiting.insert(name.clone()) { return Err(CompilerError::CyclicIdentifier(name.clone())); } if let Some(expr) = env.get(name) { - if let (Some(type_name), Expr::Array(values)) = (types.get(name), expr) { - if is_array_type(type_name) { - let encoded = encode_array_literal(values, type_name)?; - builder.add_data(&encoded)?; - *stack_depth += 1; - visiting.remove(name); - return Ok(()); + if let Some(type_name) = types.get(name) { + if let ExprKind::Array(values) = &expr.kind { + if is_array_type(type_name) { + let encoded = encode_array_literal(values, type_name)?; + builder.add_data(&encoded)?; + *stack_depth += 1; + visiting.remove(name); + return Ok(()); + } } } compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; @@ -2269,7 +2412,7 @@ fn compile_expr( visiting.remove(name); Err(CompilerError::UndefinedIdentifier(name.clone())) } - Expr::IfElse { condition, then_expr, else_expr } => { + ExprKind::IfElse { condition, then_expr, else_expr } => { compile_expr(condition, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; builder.add_op(OpIf)?; *stack_depth -= 1; @@ -2282,557 +2425,942 @@ fn compile_expr( *stack_depth = depth_before + 1; Ok(()) } - Expr::Call { name, args } => match name.as_str() { - "OpSha256" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpSHA256, - script_size, - contract_constants, - ), - "sha256" => { + ExprKind::Call { name, args, .. } => { + compile_call_expr(name.as_str(), args, &scope, builder, options, visiting, stack_depth, script_size, contract_constants) + } + ExprKind::New { name, args, .. } => match name.as_str() { + "LockingBytecodeNullData" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("LockingBytecodeNullData expects a single array argument".to_string())); + } + let script = build_null_data_script(&args[0])?; + builder.add_data(&script)?; + *stack_depth += 1; + Ok(()) + } + "ScriptPubKeyP2PK" => { if args.len() != 1 { - return Err(CompilerError::Unsupported("sha256() expects a single argument".to_string())); + return Err(CompilerError::Unsupported("ScriptPubKeyP2PK expects a single pubkey argument".to_string())); } compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpSHA256)?; + builder.add_data(&[0x00, 0x00, OpData32])?; + *stack_depth += 1; + builder.add_op(OpSwap)?; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[OpCheckSig])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; Ok(()) } - "date" => { + "ScriptPubKeyP2SH" => { if args.len() != 1 { - return Err(CompilerError::Unsupported("date() expects a single argument".to_string())); + return Err(CompilerError::Unsupported("ScriptPubKeyP2SH expects a single bytes32 argument".to_string())); } - let value = match &args[0] { - Expr::String(value) => value.as_str(), - Expr::Identifier(name) => { - if let Some(Expr::String(value)) = env.get(name) { - value.as_str() - } else { - return Err(CompilerError::Unsupported("date() expects a string literal".to_string())); - } - } - _ => return Err(CompilerError::Unsupported("date() expects a string literal".to_string())), - }; - let timestamp = parse_date_value(value)?; - builder.add_i64(timestamp)?; + compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_data(&[0x00, 0x00])?; + *stack_depth += 1; + builder.add_data(&[OpBlake2b])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[0x20])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_op(OpSwap)?; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[OpEqual])?; *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; Ok(()) } - "OpTxSubnetId" => compile_opcode_call( - name, - args, - 0, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxSubnetId, - script_size, - contract_constants, - ), - "OpTxGas" => compile_opcode_call( - name, - args, - 0, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxGas, - script_size, - contract_constants, - ), - "OpTxPayloadLen" => compile_opcode_call( - name, - args, - 0, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxPayloadLen, - script_size, - contract_constants, - ), - "OpTxPayloadSubstr" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxPayloadSubstr, - script_size, - contract_constants, - ), - "OpOutpointTxId" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpOutpointTxId, - script_size, - contract_constants, - ), - "OpOutpointIndex" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpOutpointIndex, - script_size, - contract_constants, - ), - "OpTxInputScriptSigLen" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputScriptSigLen, - script_size, - contract_constants, - ), - "OpTxInputScriptSigSubstr" => compile_opcode_call( - name, - args, - 3, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputScriptSigSubstr, - script_size, - contract_constants, - ), - "OpTxInputSeq" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputSeq, - script_size, - contract_constants, - ), - "OpTxInputIsCoinbase" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputIsCoinbase, - script_size, - contract_constants, - ), - "OpTxInputSpkLen" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputSpkLen, - script_size, - contract_constants, - ), - "OpTxInputSpkSubstr" => compile_opcode_call( - name, - args, - 3, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxInputSpkSubstr, - script_size, - contract_constants, - ), - "OpTxOutputSpkLen" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxOutputSpkLen, - script_size, - contract_constants, - ), - "OpTxOutputSpkSubstr" => compile_opcode_call( - name, - args, - 3, - &scope, - builder, - options, - visiting, - stack_depth, - OpTxOutputSpkSubstr, - script_size, - contract_constants, - ), - "OpAuthOutputCount" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpAuthOutputCount, - script_size, - contract_constants, - ), - "OpAuthOutputIdx" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpAuthOutputIdx, - script_size, - contract_constants, - ), - "OpInputCovenantId" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpInputCovenantId, - script_size, - contract_constants, - ), - "OpCovInputCount" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovInputCount, - script_size, - contract_constants, - ), - "OpCovInputIdx" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovInputIdx, - script_size, - contract_constants, - ), - "OpCovOutCount" => compile_opcode_call( - name, - args, - 1, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovOutCount, - script_size, - contract_constants, - ), - "OpCovOutputIdx" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpCovOutputIdx, - script_size, - contract_constants, - ), - "OpNum2Bin" => compile_opcode_call( - name, - args, - 2, - &scope, - builder, - options, - visiting, - stack_depth, - OpNum2Bin, - script_size, - contract_constants, - ), - "OpBin2Num" => compile_opcode_call( - name, - args, - 1, - &scope, + "ScriptPubKeyP2SHFromRedeemScript" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported( + "ScriptPubKeyP2SHFromRedeemScript expects a single redeem_script argument".to_string(), + )); + } + compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_op(OpBlake2b)?; + builder.add_data(&[0x00, 0x00])?; + *stack_depth += 1; + builder.add_data(&[OpBlake2b])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[0x20])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_op(OpSwap)?; + builder.add_op(OpCat)?; + *stack_depth -= 1; + builder.add_data(&[OpEqual])?; + *stack_depth += 1; + builder.add_op(OpCat)?; + *stack_depth -= 1; + Ok(()) + } + name => Err(CompilerError::Unsupported(format!("unknown constructor: {name}"))), + }, + ExprKind::Unary { op, expr } => { + compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + match op { + UnaryOp::Not => builder.add_op(OpNot)?, + UnaryOp::Neg => builder.add_op(OpNegate)?, + }; + Ok(()) + } + ExprKind::Binary { op, left, right } => { + let bytes_eq = + matches!(op, BinaryOp::Eq | BinaryOp::Ne) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); + let bytes_add = matches!(op, BinaryOp::Add) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); + if bytes_add { + compile_concat_operand( + left, + env, + params, + types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + compile_concat_operand( + right, + env, + params, + types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + } else { + compile_expr(left, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + compile_expr(right, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + } + match op { + BinaryOp::Or => { + builder.add_op(OpBoolOr)?; + } + BinaryOp::And => { + builder.add_op(OpBoolAnd)?; + } + BinaryOp::BitOr => { + builder.add_op(OpOr)?; + } + BinaryOp::BitXor => { + builder.add_op(OpXor)?; + } + BinaryOp::BitAnd => { + builder.add_op(OpAnd)?; + } + BinaryOp::Eq => { + builder.add_op(if bytes_eq { OpEqual } else { OpNumEqual })?; + } + BinaryOp::Ne => { + if bytes_eq { + builder.add_op(OpEqual)?; + builder.add_op(OpNot)?; + } else { + builder.add_op(OpNumNotEqual)?; + } + } + BinaryOp::Lt => { + builder.add_op(OpLessThan)?; + } + BinaryOp::Le => { + builder.add_op(OpLessThanOrEqual)?; + } + BinaryOp::Gt => { + builder.add_op(OpGreaterThan)?; + } + BinaryOp::Ge => { + builder.add_op(OpGreaterThanOrEqual)?; + } + BinaryOp::Add => { + if bytes_add { + builder.add_op(OpCat)?; + } else { + builder.add_op(OpAdd)?; + } + } + BinaryOp::Sub => { + builder.add_op(OpSub)?; + } + BinaryOp::Mul => { + builder.add_op(OpMul)?; + } + BinaryOp::Div => { + builder.add_op(OpDiv)?; + } + BinaryOp::Mod => { + builder.add_op(OpMod)?; + } + } + *stack_depth -= 1; + Ok(()) + } + ExprKind::Split { source, index, part, .. } => compile_split_part( + source, + index, + *part, + env, + params, + types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + ), + ExprKind::UnarySuffix { source, kind, .. } => match kind { + UnarySuffixKind::Length => compile_length_expr( + source, + env, + params, + types, builder, options, visiting, stack_depth, - OpBin2Num, script_size, contract_constants, ), - "OpChainblockSeqCommit" => compile_opcode_call( - name, - args, - 1, - &scope, + UnarySuffixKind::Reverse => Err(CompilerError::Unsupported("reverse() is not supported".to_string())), + }, + ExprKind::ArrayIndex { source, index } => { + let resolved_source = match source.as_ref() { + Expr { kind: ExprKind::Identifier(_), .. } => source.as_ref().clone(), + _ => resolve_expr(*source.clone(), env, visiting)?, + }; + let element_type = match &resolved_source.kind { + ExprKind::Identifier(name) => { + let type_name = types.get(name).or_else(|| { + env.get(name).and_then(|value| match &value.kind { + ExprKind::Identifier(inner) => types.get(inner), + _ => None, + }) + }); + type_name + .and_then(|t| array_element_type(t)) + .ok_or_else(|| CompilerError::Unsupported(format!("array index requires array identifier: {name}")))? + } + _ => return Err(CompilerError::Unsupported("array index requires array identifier".to_string())), + }; + let element_size = fixed_type_size(&element_type) + .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; + compile_expr( + &resolved_source, + env, + params, + types, builder, options, visiting, stack_depth, - OpChainblockSeqCommit, script_size, contract_constants, - ), - "bytes" => { - if args.is_empty() || args.len() > 2 { - return Err(CompilerError::Unsupported("bytes() expects one or two arguments".to_string())); - } - if args.len() == 2 { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - compile_expr( - &args[1], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - return Ok(()); - } - match &args[0] { - Expr::String(value) => { - builder.add_data(value.as_bytes())?; - *stack_depth += 1; - Ok(()) - } - Expr::Identifier(name) => { - if let Some(Expr::String(value)) = env.get(name) { - builder.add_data(value.as_bytes())?; - *stack_depth += 1; - return Ok(()); - } - if expr_is_bytes(&args[0], env, types) { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - return Ok(()); - } - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_i64(8)?; - *stack_depth += 1; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - Ok(()) - } - _ => { - if expr_is_bytes(&args[0], env, types) { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - Ok(()) - } else { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_i64(8)?; - *stack_depth += 1; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - Ok(()) - } - } + )?; + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_i64(element_size)?; + *stack_depth += 1; + builder.add_op(OpMul)?; + *stack_depth -= 1; + builder.add_op(OpDup)?; + *stack_depth += 1; + builder.add_i64(element_size)?; + *stack_depth += 1; + builder.add_op(OpAdd)?; + *stack_depth -= 1; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + if element_type == "int" { + builder.add_op(OpBin2Num)?; + } + Ok(()) + } + ExprKind::Slice { source, start, end, .. } => { + compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + compile_expr(start, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + compile_expr(end, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + + builder.add_op(Op2Dup)?; + *stack_depth += 2; + builder.add_op(OpSwap)?; + builder.add_op(OpSub)?; + *stack_depth -= 1; + builder.add_op(OpSwap)?; + builder.add_op(OpDrop)?; + *stack_depth -= 1; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + Ok(()) + } + ExprKind::Nullary(op) => { + match op { + NullaryOp::ActiveInputIndex => { + builder.add_op(OpTxInputIndex)?; + } + NullaryOp::ActiveScriptPubKey => { + builder.add_op(OpTxInputIndex)?; + builder.add_op(OpTxInputSpk)?; + } + NullaryOp::ThisScriptSize => { + let size = script_size + .ok_or_else(|| CompilerError::Unsupported("this.scriptSize is only available at compile time".to_string()))?; + builder.add_i64(size)?; + } + NullaryOp::ThisScriptSizeDataPrefix => { + let size = script_size.ok_or_else(|| { + CompilerError::Unsupported("this.scriptSizeDataPrefix is only available at compile time".to_string()) + })?; + let size: usize = size.try_into().map_err(|_| { + CompilerError::Unsupported("this.scriptSizeDataPrefix requires a non-negative script size".to_string()) + })?; + let prefix = data_prefix(size); + builder.add_data(&prefix)?; + } + NullaryOp::TxInputsLength => { + builder.add_op(OpTxInputCount)?; + } + NullaryOp::TxOutputsLength => { + builder.add_op(OpTxOutputCount)?; + } + NullaryOp::TxVersion => { + builder.add_op(OpTxVersion)?; + } + NullaryOp::TxLockTime => { + builder.add_op(OpTxLockTime)?; } } - "length" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("length() expects a single argument".to_string())); + *stack_depth += 1; + Ok(()) + } + ExprKind::Introspection { kind, index, .. } => { + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + match kind { + IntrospectionKind::InputValue => { + builder.add_op(OpTxInputAmount)?; } - if let Expr::Identifier(name) = &args[0] { - if let Some(type_name) = types.get(name) { - // Check if this is a fixed-size array type[N] (supporting constants) - if let Some(array_size) = array_size_with_constants(type_name, contract_constants) { - // Compile-time length for fixed-size arrays - builder.add_i64(array_size as i64)?; - *stack_depth += 1; - return Ok(()); - } - // Runtime length for dynamic arrays - if let Some(element_size) = array_element_size(type_name) { - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - builder.add_op(OpSize)?; - builder.add_op(OpSwap)?; - builder.add_op(OpDrop)?; - builder.add_i64(element_size)?; - *stack_depth += 1; - builder.add_op(OpDiv)?; - *stack_depth -= 1; - return Ok(()); - } - } + IntrospectionKind::InputScriptPubKey => { + builder.add_op(OpTxInputSpk)?; } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + IntrospectionKind::InputSigScript => { + builder.add_op(OpDup)?; + builder.add_op(OpTxInputScriptSigLen)?; + builder.add_i64(0)?; + builder.add_op(OpSwap)?; + builder.add_op(OpTxInputScriptSigSubstr)?; + } + IntrospectionKind::InputOutpointTransactionHash => { + builder.add_op(OpOutpointTxId)?; + } + IntrospectionKind::InputOutpointIndex => { + builder.add_op(OpOutpointIndex)?; + } + IntrospectionKind::InputSequenceNumber => { + builder.add_op(OpTxInputSeq)?; + } + IntrospectionKind::OutputValue => { + builder.add_op(OpTxOutputAmount)?; + } + IntrospectionKind::OutputScriptPubKey => { + builder.add_op(OpTxOutputSpk)?; + } + } + Ok(()) + } + ExprKind::DateLiteral(value) => { + builder.add_i64(*value)?; + *stack_depth += 1; + Ok(()) + } + ExprKind::NumberWithUnit { .. } => { + Err(CompilerError::Unsupported("number units must be normalized during parsing".to_string())) + } + } +} + +#[allow(clippy::too_many_arguments)] +fn compile_split_part<'i>( + source: &Expr<'i>, + index: &Expr<'i>, + part: SplitPart, + env: &HashMap>, + params: &HashMap, + types: &HashMap, + builder: &mut ScriptBuilder, + options: CompileOptions, + visiting: &mut HashSet, + stack_depth: &mut i64, + script_size: Option, + contract_constants: &HashMap>, +) -> Result<(), CompilerError> { + compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + match part { + SplitPart::Left => { + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_i64(0)?; + *stack_depth += 1; + builder.add_op(OpSwap)?; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + Ok(()) + } + SplitPart::Right => { + builder.add_op(OpSize)?; + *stack_depth += 1; + compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_op(OpSwap)?; + builder.add_op(OpSubstr)?; + *stack_depth -= 2; + Ok(()) + } + } +} + +fn expr_is_bytes<'i>(expr: &Expr<'i>, env: &HashMap>, types: &HashMap) -> bool { + let mut visiting = HashSet::new(); + expr_is_bytes_inner(expr, env, types, &mut visiting) +} + +fn expr_is_bytes_inner<'i>( + expr: &Expr<'i>, + env: &HashMap>, + types: &HashMap, + visiting: &mut HashSet, +) -> bool { + match &expr.kind { + ExprKind::Byte(_) => true, + ExprKind::String(_) => true, + ExprKind::Array(values) => values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))), + ExprKind::Slice { .. } => true, + ExprKind::New { name, .. } => matches!( + name.as_str(), + "LockingBytecodeNullData" | "ScriptPubKeyP2PK" | "ScriptPubKeyP2SH" | "ScriptPubKeyP2SHFromRedeemScript" + ), + ExprKind::Call { name, .. } => { + let name = name.as_str(); + matches!( + name, + "bytes" + | "blake2b" + | "sha256" + | "OpSha256" + | "OpTxSubnetId" + | "OpTxPayloadSubstr" + | "OpOutpointTxId" + | "OpTxInputScriptSigSubstr" + | "OpTxInputSeq" + | "OpTxInputSpkSubstr" + | "OpTxOutputSpkSubstr" + | "OpInputCovenantId" + | "OpNum2Bin" + | "OpChainblockSeqCommit" + ) || name.starts_with("byte[") + } + ExprKind::Split { .. } => true, + ExprKind::Binary { op: BinaryOp::Add, left, right } => { + expr_is_bytes_inner(left, env, types, visiting) || expr_is_bytes_inner(right, env, types, visiting) + } + ExprKind::IfElse { condition: _, then_expr, else_expr } => { + expr_is_bytes_inner(then_expr, env, types, visiting) && expr_is_bytes_inner(else_expr, env, types, visiting) + } + ExprKind::Introspection { kind, .. } => matches!( + kind, + IntrospectionKind::InputScriptPubKey + | IntrospectionKind::InputSigScript + | IntrospectionKind::InputOutpointTransactionHash + | IntrospectionKind::OutputScriptPubKey + ), + ExprKind::Nullary(NullaryOp::ActiveScriptPubKey) => true, + ExprKind::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, + ExprKind::ArrayIndex { source, .. } => match &source.kind { + ExprKind::Identifier(name) => { + types.get(name).and_then(|type_name| array_element_type(type_name)).map(|element| element != "int").unwrap_or(false) + } + _ => false, + }, + ExprKind::Identifier(name) => { + if !visiting.insert(name.clone()) { + return false; + } + if let Some(expr) = env.get(name) { + let result = expr_is_bytes_inner(expr, env, types, visiting) + || types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false); + visiting.remove(name); + return result; + } + visiting.remove(name); + types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false) + } + ExprKind::UnarySuffix { kind, .. } => matches!(kind, UnarySuffixKind::Reverse), + _ => false, + } +} + +fn compile_length_expr<'i>( + expr: &Expr<'i>, + env: &HashMap>, + params: &HashMap, + types: &HashMap, + builder: &mut ScriptBuilder, + options: CompileOptions, + visiting: &mut HashSet, + stack_depth: &mut i64, + script_size: Option, + contract_constants: &HashMap>, +) -> Result<(), CompilerError> { + if let ExprKind::Identifier(name) = &expr.kind { + if let Some(type_name) = types.get(name) { + if let Some(size) = array_size_with_constants(type_name, contract_constants) { + builder.add_i64(size as i64)?; + *stack_depth += 1; + return Ok(()); + } + if let Some(element_size) = array_element_size(type_name) { + compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; builder.add_op(OpSize)?; - Ok(()) + builder.add_op(OpSwap)?; + builder.add_op(OpDrop)?; + builder.add_i64(element_size)?; + *stack_depth += 1; + builder.add_op(OpDiv)?; + *stack_depth -= 1; + return Ok(()); } - "int" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("int() expects a single argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - Ok(()) + } + } + if let ExprKind::Array(values) = &expr.kind { + builder.add_i64(values.len() as i64)?; + *stack_depth += 1; + return Ok(()); + } + compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; + builder.add_op(OpSize)?; + Ok(()) +} + +fn compile_call_expr<'i>( + name: &str, + args: &[Expr<'i>], + scope: &CompilationScope<'_, 'i>, + builder: &mut ScriptBuilder, + options: CompileOptions, + visiting: &mut HashSet, + stack_depth: &mut i64, + script_size: Option, + contract_constants: &HashMap>, +) -> Result<(), CompilerError> { + match name { + "OpSha256" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpSHA256, + script_size, + contract_constants, + ), + "sha256" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("sha256() expects a single argument".to_string())); } - "sig" | "pubkey" | "datasig" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - Ok(()) + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpSHA256)?; + Ok(()) + } + "OpTxSubnetId" => compile_opcode_call( + name, + args, + 0, + scope, + builder, + options, + visiting, + stack_depth, + OpTxSubnetId, + script_size, + contract_constants, + ), + "OpTxGas" => compile_opcode_call( + name, + args, + 0, + scope, + builder, + options, + visiting, + stack_depth, + OpTxGas, + script_size, + contract_constants, + ), + "OpTxPayloadLen" => compile_opcode_call( + name, + args, + 0, + scope, + builder, + options, + visiting, + stack_depth, + OpTxPayloadLen, + script_size, + contract_constants, + ), + "OpTxPayloadSubstr" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpTxPayloadSubstr, + script_size, + contract_constants, + ), + "OpOutpointTxId" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpOutpointTxId, + script_size, + contract_constants, + ), + "OpOutpointIndex" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpOutpointIndex, + script_size, + contract_constants, + ), + "OpTxInputScriptSigLen" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputScriptSigLen, + script_size, + contract_constants, + ), + "OpTxInputScriptSigSubstr" => compile_opcode_call( + name, + args, + 3, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputScriptSigSubstr, + script_size, + contract_constants, + ), + "OpTxInputSeq" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputSeq, + script_size, + contract_constants, + ), + "OpTxInputIsCoinbase" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputIsCoinbase, + script_size, + contract_constants, + ), + "OpTxInputSpkLen" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputSpkLen, + script_size, + contract_constants, + ), + "OpTxInputSpkSubstr" => compile_opcode_call( + name, + args, + 3, + scope, + builder, + options, + visiting, + stack_depth, + OpTxInputSpkSubstr, + script_size, + contract_constants, + ), + "OpTxOutputSpkLen" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpTxOutputSpkLen, + script_size, + contract_constants, + ), + "OpTxOutputSpkSubstr" => compile_opcode_call( + name, + args, + 3, + scope, + builder, + options, + visiting, + stack_depth, + OpTxOutputSpkSubstr, + script_size, + contract_constants, + ), + "OpAuthOutputCount" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpAuthOutputCount, + script_size, + contract_constants, + ), + "OpAuthOutputIdx" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpAuthOutputIdx, + script_size, + contract_constants, + ), + "OpInputCovenantId" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpInputCovenantId, + script_size, + contract_constants, + ), + "OpCovInputCount" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpCovInputCount, + script_size, + contract_constants, + ), + "OpCovInputIdx" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpCovInputIdx, + script_size, + contract_constants, + ), + "OpCovOutCount" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpCovOutCount, + script_size, + contract_constants, + ), + "OpCovOutputIdx" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpCovOutputIdx, + script_size, + contract_constants, + ), + "OpNum2Bin" => compile_opcode_call( + name, + args, + 2, + scope, + builder, + options, + visiting, + stack_depth, + OpNum2Bin, + script_size, + contract_constants, + ), + "OpBin2Num" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpBin2Num, + script_size, + contract_constants, + ), + "OpChainblockSeqCommit" => compile_opcode_call( + name, + args, + 1, + scope, + builder, + options, + visiting, + stack_depth, + OpChainblockSeqCommit, + script_size, + contract_constants, + ), + "bytes" => { + if args.is_empty() || args.len() > 2 { + return Err(CompilerError::Unsupported("bytes() expects one or two arguments".to_string())); + } + if args.len() == 2 { + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + compile_expr( + &args[1], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; + return Ok(()); } - name if name.starts_with("byte[") && name.ends_with(']') => { - let size_part = &name[5..name.len() - 1]; - if size_part.is_empty() { - // Handle byte[] cast (dynamic array) - just compile the argument as-is - if args.len() != 1 && args.len() != 2 { - return Err(CompilerError::Unsupported(format!("{name}() expects 1 or 2 arguments"))); + match &args[0].kind { + ExprKind::String(value) => { + builder.add_data(value.as_bytes())?; + *stack_depth += 1; + Ok(()) + } + ExprKind::Identifier(name) => { + if let Some(expr) = scope.env.get(name) { + if let ExprKind::String(value) = &expr.kind { + builder.add_data(value.as_bytes())?; + *stack_depth += 1; + return Ok(()); + } } - compile_expr( - &args[0], - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - if args.len() == 2 { - // byte[](value, size) - OpNum2Bin with size parameter + if expr_is_bytes(&args[0], scope.env, scope.types) { compile_expr( - &args[1], - env, - params, - types, + &args[0], + scope.env, + scope.params, + scope.types, builder, options, visiting, @@ -2840,23 +3368,13 @@ fn compile_expr( script_size, contract_constants, )?; - *stack_depth += 1; - builder.add_op(OpNum2Bin)?; - *stack_depth -= 1; - } - Ok(()) - } else { - // Handle byte[N] cast - extract size from byte[N] - let size = - size_part.parse::().map_err(|_| CompilerError::Unsupported(format!("{name}() is not supported")))?; - if args.len() != 1 { - return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); + return Ok(()); } compile_expr( &args[0], - env, - params, - types, + scope.env, + scope.params, + scope.types, builder, options, visiting, @@ -2864,273 +3382,75 @@ fn compile_expr( script_size, contract_constants, )?; - builder.add_i64(size)?; + builder.add_i64(8)?; *stack_depth += 1; builder.add_op(OpNum2Bin)?; *stack_depth -= 1; Ok(()) } - } - "blake2b" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("blake2b() expects a single argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpBlake2b)?; - Ok(()) - } - "checkSig" => { - if args.len() != 2 { - return Err(CompilerError::Unsupported("checkSig() expects 2 arguments".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(&args[1], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpCheckSig)?; - *stack_depth -= 1; - Ok(()) - } - "checkDataSig" => { - // TODO: Remove this stub - for arg in args { - compile_expr(arg, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - } - for _ in 0..args.len() { - builder.add_op(OpDrop)?; - *stack_depth -= 1; - } - builder.add_op(OpTrue)?; - *stack_depth += 1; - Ok(()) - } - _ => Err(CompilerError::Unsupported(format!("unknown function call: {name}"))), - }, - Expr::New { name, args } => match name.as_str() { - "LockingBytecodeNullData" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("LockingBytecodeNullData expects a single array argument".to_string())); - } - let script = build_null_data_script(&args[0])?; - builder.add_data(&script)?; - *stack_depth += 1; - Ok(()) - } - "ScriptPubKeyP2PK" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("ScriptPubKeyP2PK expects a single pubkey argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_data(&[0x00, 0x00, OpData32])?; - *stack_depth += 1; - builder.add_op(OpSwap)?; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[OpCheckSig])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - Ok(()) - } - "ScriptPubKeyP2SH" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported("ScriptPubKeyP2SH expects a single bytes32 argument".to_string())); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_data(&[0x00, 0x00])?; - *stack_depth += 1; - builder.add_data(&[OpBlake2b])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[0x20])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_op(OpSwap)?; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[OpEqual])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - Ok(()) - } - "ScriptPubKeyP2SHFromRedeemScript" => { - if args.len() != 1 { - return Err(CompilerError::Unsupported( - "ScriptPubKeyP2SHFromRedeemScript expects a single redeem_script argument".to_string(), - )); - } - compile_expr(&args[0], env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpBlake2b)?; - builder.add_data(&[0x00, 0x00])?; - *stack_depth += 1; - builder.add_data(&[OpBlake2b])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[0x20])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_op(OpSwap)?; - builder.add_op(OpCat)?; - *stack_depth -= 1; - builder.add_data(&[OpEqual])?; - *stack_depth += 1; - builder.add_op(OpCat)?; - *stack_depth -= 1; - Ok(()) - } - _ => Err(CompilerError::Unsupported(format!("unknown constructor: {name}"))), - }, - Expr::Unary { op, expr } => { - compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - match op { - UnaryOp::Not => builder.add_op(OpNot)?, - UnaryOp::Neg => builder.add_op(OpNegate)?, - }; - Ok(()) - } - Expr::Binary { op, left, right } => { - let bytes_eq = - matches!(op, BinaryOp::Eq | BinaryOp::Ne) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); - let bytes_add = matches!(op, BinaryOp::Add) && (expr_is_bytes(left, env, types) || expr_is_bytes(right, env, types)); - if bytes_add { - compile_concat_operand( - left, - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - compile_concat_operand( - right, - env, - params, - types, - builder, - options, - visiting, - stack_depth, - script_size, - contract_constants, - )?; - } else { - compile_expr(left, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(right, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - } - match op { - BinaryOp::Or => { - builder.add_op(OpBoolOr)?; - } - BinaryOp::And => { - builder.add_op(OpBoolAnd)?; - } - BinaryOp::BitOr => { - builder.add_op(OpOr)?; - } - BinaryOp::BitXor => { - builder.add_op(OpXor)?; - } - BinaryOp::BitAnd => { - builder.add_op(OpAnd)?; - } - BinaryOp::Eq => { - builder.add_op(if bytes_eq { OpEqual } else { OpNumEqual })?; - } - BinaryOp::Ne => { - if bytes_eq { - builder.add_op(OpEqual)?; - builder.add_op(OpNot)?; - } else { - builder.add_op(OpNumNotEqual)?; - } - } - BinaryOp::Lt => { - builder.add_op(OpLessThan)?; - } - BinaryOp::Le => { - builder.add_op(OpLessThanOrEqual)?; - } - BinaryOp::Gt => { - builder.add_op(OpGreaterThan)?; - } - BinaryOp::Ge => { - builder.add_op(OpGreaterThanOrEqual)?; - } - BinaryOp::Add => { - if bytes_add { - builder.add_op(OpCat)?; + _ => { + if expr_is_bytes(&args[0], scope.env, scope.types) { + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + Ok(()) } else { - builder.add_op(OpAdd)?; - } - } - BinaryOp::Sub => { - builder.add_op(OpSub)?; - } - BinaryOp::Mul => { - builder.add_op(OpMul)?; - } - BinaryOp::Div => { - builder.add_op(OpDiv)?; - } - BinaryOp::Mod => { - builder.add_op(OpMod)?; - } - } - *stack_depth -= 1; - Ok(()) - } - Expr::Split { source, index, part } => { - compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - match part { - SplitPart::Left => { - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_i64(0)?; - *stack_depth += 1; - builder.add_op(OpSwap)?; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; - } - SplitPart::Right => { - builder.add_op(OpSize)?; - *stack_depth += 1; - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_op(OpSwap)?; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_i64(8)?; + *stack_depth += 1; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; + Ok(()) + } } } - Ok(()) } - Expr::ArrayIndex { source, index } => { - let resolved_source = match source.as_ref() { - Expr::Identifier(_) => source.as_ref().clone(), - _ => resolve_expr(*source.clone(), env, visiting)?, - }; - let element_type = match &resolved_source { - Expr::Identifier(name) => { - let type_name = types.get(name).or_else(|| { - env.get(name).and_then(|value| if let Expr::Identifier(inner) = value { types.get(inner) } else { None }) - }); - type_name - .and_then(|t| array_element_type(t)) - .ok_or_else(|| CompilerError::Unsupported(format!("array index requires array identifier: {name}")))? - } - _ => return Err(CompilerError::Unsupported("array index requires array identifier".to_string())), - }; - let element_size = fixed_type_size(&element_type) - .ok_or_else(|| CompilerError::Unsupported("array element type must have known size".to_string()))?; + "length" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("length() expects a single argument".to_string())); + } + compile_length_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + ) + } + "int" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("int() expects a single argument".to_string())); + } compile_expr( - &resolved_source, - env, - params, - types, + &args[0], + scope.env, + scope.params, + scope.types, builder, options, visiting, @@ -3138,199 +3458,181 @@ fn compile_expr( script_size, contract_constants, )?; - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - builder.add_i64(element_size)?; - *stack_depth += 1; - builder.add_op(OpMul)?; - *stack_depth -= 1; - builder.add_op(OpDup)?; - *stack_depth += 1; - builder.add_i64(element_size)?; - *stack_depth += 1; - builder.add_op(OpAdd)?; - *stack_depth -= 1; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; - if element_type == "int" { - builder.add_op(OpBin2Num)?; - } Ok(()) } - Expr::Slice { source, start, end } => { - compile_expr(source, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(start, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - compile_expr(end, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - - builder.add_op(Op2Dup)?; - *stack_depth += 2; - builder.add_op(OpSwap)?; - builder.add_op(OpSub)?; - *stack_depth -= 1; - builder.add_op(OpSwap)?; - builder.add_op(OpDrop)?; - *stack_depth -= 1; - builder.add_op(OpSubstr)?; - *stack_depth -= 2; + "sig" | "pubkey" | "datasig" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); + } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; Ok(()) } - Expr::Nullary(op) => { - match op { - NullaryOp::ActiveInputIndex => { - builder.add_op(OpTxInputIndex)?; - } - NullaryOp::ActiveScriptPubKey => { - builder.add_op(OpTxInputIndex)?; - builder.add_op(OpTxInputSpk)?; - } - NullaryOp::ThisScriptSize => { - let size = script_size - .ok_or_else(|| CompilerError::Unsupported("this.scriptSize is only available at compile time".to_string()))?; - builder.add_i64(size)?; - } - NullaryOp::ThisScriptSizeDataPrefix => { - let size = script_size.ok_or_else(|| { - CompilerError::Unsupported("this.scriptSizeDataPrefix is only available at compile time".to_string()) - })?; - let size: usize = size.try_into().map_err(|_| { - CompilerError::Unsupported("this.scriptSizeDataPrefix requires a non-negative script size".to_string()) - })?; - let prefix = data_prefix(size); - builder.add_data(&prefix)?; - } - NullaryOp::TxInputsLength => { - builder.add_op(OpTxInputCount)?; - } - NullaryOp::TxOutputsLength => { - builder.add_op(OpTxOutputCount)?; - } - NullaryOp::TxVersion => { - builder.add_op(OpTxVersion)?; + name if name.starts_with("byte[") && name.ends_with(']') => { + let size_part = &name[5..name.len() - 1]; + if size_part.is_empty() { + // Handle byte[] cast (dynamic array) - just compile the argument as-is + if args.len() != 1 && args.len() != 2 { + return Err(CompilerError::Unsupported(format!("{name}() expects 1 or 2 arguments"))); + } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + if args.len() == 2 { + // byte[](value, size) - OpNum2Bin with size parameter + compile_expr( + &args[1], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + *stack_depth += 1; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; } - NullaryOp::TxLockTime => { - builder.add_op(OpTxLockTime)?; + Ok(()) + } else { + // Handle byte[N] cast - extract size from byte[N] + let size = size_part.parse::().map_err(|_| CompilerError::Unsupported(format!("{name}() is not supported")))?; + if args.len() != 1 { + return Err(CompilerError::Unsupported(format!("{name}() expects a single argument"))); } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_i64(size)?; + *stack_depth += 1; + builder.add_op(OpNum2Bin)?; + *stack_depth -= 1; + Ok(()) } - *stack_depth += 1; - Ok(()) } - Expr::Introspection { kind, index } => { - compile_expr(index, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; - match kind { - IntrospectionKind::InputValue => { - builder.add_op(OpTxInputAmount)?; - } - IntrospectionKind::InputScriptPubKey => { - builder.add_op(OpTxInputSpk)?; - } - IntrospectionKind::InputSigScript => { - builder.add_op(OpDup)?; - builder.add_op(OpTxInputScriptSigLen)?; - builder.add_i64(0)?; - builder.add_op(OpSwap)?; - builder.add_op(OpTxInputScriptSigSubstr)?; - } - IntrospectionKind::OutputValue => { - builder.add_op(OpTxOutputAmount)?; - } - IntrospectionKind::OutputScriptPubKey => { - builder.add_op(OpTxOutputSpk)?; - } + "blake2b" => { + if args.len() != 1 { + return Err(CompilerError::Unsupported("blake2b() expects a single argument".to_string())); } + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpBlake2b)?; Ok(()) } - } -} - -fn expr_is_bytes(expr: &Expr, env: &HashMap, types: &HashMap) -> bool { - let mut visiting = HashSet::new(); - expr_is_bytes_inner(expr, env, types, &mut visiting) -} - -fn expr_is_bytes_inner( - expr: &Expr, - env: &HashMap, - types: &HashMap, - visiting: &mut HashSet, -) -> bool { - match expr { - Expr::Byte(_) => true, - Expr::Array(values) => is_byte_array(&Expr::Array(values.clone())), - Expr::StateObject(_) => false, - Expr::String(_) => true, - Expr::Slice { .. } => true, - Expr::New { name, .. } => matches!( - name.as_str(), - "LockingBytecodeNullData" | "ScriptPubKeyP2PK" | "ScriptPubKeyP2SH" | "ScriptPubKeyP2SHFromRedeemScript" - ), - Expr::Call { name, .. } => { - matches!( - name.as_str(), - "blake2b" - | "sha256" - | "OpSha256" - | "OpTxSubnetId" - | "OpTxPayloadSubstr" - | "OpOutpointTxId" - | "OpTxInputScriptSigSubstr" - | "OpTxInputSeq" - | "OpTxInputSpkSubstr" - | "OpTxOutputSpkSubstr" - | "OpInputCovenantId" - | "OpNum2Bin" - | "OpChainblockSeqCommit" - ) || name.starts_with("byte[") - } - Expr::Split { .. } => true, - Expr::Binary { op: BinaryOp::Add, left, right } => { - expr_is_bytes_inner(left, env, types, visiting) || expr_is_bytes_inner(right, env, types, visiting) - } - Expr::IfElse { condition: _, then_expr, else_expr } => { - expr_is_bytes_inner(then_expr, env, types, visiting) && expr_is_bytes_inner(else_expr, env, types, visiting) - } - Expr::Introspection { kind, .. } => { - matches!( - kind, - IntrospectionKind::InputScriptPubKey | IntrospectionKind::InputSigScript | IntrospectionKind::OutputScriptPubKey - ) - } - Expr::Nullary(NullaryOp::ActiveScriptPubKey) => true, - Expr::Nullary(NullaryOp::ThisScriptSizeDataPrefix) => true, - Expr::ArrayIndex { source, .. } => match source.as_ref() { - Expr::Identifier(name) => { - types.get(name).and_then(|type_name| array_element_type(type_name)).map(|element| element != "int").unwrap_or(false) + "checkSig" => { + if args.len() != 2 { + return Err(CompilerError::Unsupported("checkSig() expects 2 arguments".to_string())); } - _ => false, - }, - Expr::Identifier(name) => { - if !visiting.insert(name.clone()) { - return false; + compile_expr( + &args[0], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + compile_expr( + &args[1], + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; + builder.add_op(OpCheckSig)?; + *stack_depth -= 1; + Ok(()) + } + "checkDataSig" => { + // TODO: Remove this stub + for arg in args { + compile_expr( + arg, + scope.env, + scope.params, + scope.types, + builder, + options, + visiting, + stack_depth, + script_size, + contract_constants, + )?; } - if let Some(expr) = env.get(name) { - let result = expr_is_bytes_inner(expr, env, types, visiting) - || types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false); - visiting.remove(name); - return result; + for _ in 0..args.len() { + builder.add_op(OpDrop)?; + *stack_depth -= 1; } - visiting.remove(name); - types.get(name).map(|type_name| is_bytes_type(type_name)).unwrap_or(false) + builder.add_op(OpTrue)?; + *stack_depth += 1; + Ok(()) } - _ => false, + _ => Err(CompilerError::Unsupported(format!("unknown function call: {name}"))), } } #[allow(clippy::too_many_arguments)] -fn compile_opcode_call( +fn compile_opcode_call<'i>( name: &str, - args: &[Expr], + args: &[Expr<'i>], expected_args: usize, - scope: &CompilationScope, + scope: &CompilationScope<'_, 'i>, builder: &mut ScriptBuilder, options: CompileOptions, visiting: &mut HashSet, stack_depth: &mut i64, opcode: u8, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { if args.len() != expected_args { return Err(CompilerError::Unsupported(format!("{name}() expects {expected_args} argument(s)"))); @@ -3354,9 +3656,9 @@ fn compile_opcode_call( Ok(()) } -fn compile_concat_operand( - expr: &Expr, - env: &HashMap, +fn compile_concat_operand<'i>( + expr: &Expr<'i>, + env: &HashMap>, params: &HashMap, types: &HashMap, builder: &mut ScriptBuilder, @@ -3364,7 +3666,7 @@ fn compile_concat_operand( visiting: &mut HashSet, stack_depth: &mut i64, script_size: Option, - contract_constants: &HashMap, + contract_constants: &HashMap>, ) -> Result<(), CompilerError> { compile_expr(expr, env, params, types, builder, options, visiting, stack_depth, script_size, contract_constants)?; if !expr_is_bytes(expr, env, types) { @@ -3389,35 +3691,40 @@ fn is_bytes_type(type_name: &str) -> bool { is_array_type(type_name) } -fn build_null_data_script(arg: &Expr) -> Result, CompilerError> { - let elements = match arg { - Expr::Array(items) => items, +fn build_null_data_script<'i>(arg: &Expr<'i>) -> Result, CompilerError> { + let elements = match &arg.kind { + ExprKind::Array(items) => items, _ => return Err(CompilerError::Unsupported("LockingBytecodeNullData expects an array literal".to_string())), }; let mut builder = ScriptBuilder::new(); builder.add_op(OpReturn)?; for item in elements { - match item { - Expr::Int(value) => { + match &item.kind { + ExprKind::Int(value) => { + builder.add_i64(*value)?; + } + ExprKind::DateLiteral(value) => { builder.add_i64(*value)?; } - Expr::Array(values) if is_byte_array(&Expr::Array(values.clone())) => { - // Handle byte arrays - let bytes: Vec = values.iter().filter_map(|v| if let Expr::Byte(b) = v { Some(*b) } else { None }).collect(); + ExprKind::Array(values) if values.iter().all(|value| matches!(&value.kind, ExprKind::Byte(_))) => { + let bytes: Vec = values + .iter() + .filter_map(|value| if let ExprKind::Byte(byte) = &value.kind { Some(*byte) } else { None }) + .collect(); builder.add_data(&bytes)?; } - Expr::String(value) => { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; } - Expr::Call { name, args } if name == "byte[]" => { + ExprKind::Call { name, args, .. } if name == "bytes" || name == "byte[]" => { if args.len() != 1 { return Err(CompilerError::Unsupported( "byte[]() in LockingBytecodeNullData expects a single argument".to_string(), )); } - match &args[0] { - Expr::String(value) => { + match &args[0].kind { + ExprKind::String(value) => { builder.add_data(value.as_bytes())?; } _ => { @@ -3427,7 +3734,9 @@ fn build_null_data_script(arg: &Expr) -> Result, CompilerError> { } } } - _ => return Err(CompilerError::Unsupported("LockingBytecodeNullData only supports int or bytes literals".to_string())), + _ => { + return Err(CompilerError::Unsupported("LockingBytecodeNullData only supports int or bytes literals".to_string())); + } } } @@ -3438,14 +3747,6 @@ fn build_null_data_script(arg: &Expr) -> Result, CompilerError> { Ok(spk_bytes) } -fn parse_date_value(value: &str) -> Result { - let timestamp = NaiveDateTime::parse_from_str(value, "%Y-%m-%dT%H:%M:%S") - .map_err(|_| CompilerError::InvalidLiteral("invalid date literal".to_string()))? - .and_utc() - .timestamp(); - Ok(timestamp) -} - fn data_prefix(data_len: usize) -> Vec { let dummy_data = vec![0u8; data_len]; let mut builder = ScriptBuilder::new(); diff --git a/silverscript-lang/src/diagnostic/mod.rs b/silverscript-lang/src/diagnostic/mod.rs new file mode 100644 index 00000000..88e1e5b4 --- /dev/null +++ b/silverscript-lang/src/diagnostic/mod.rs @@ -0,0 +1,5 @@ +mod parse; +mod parse_diagnostics; + +pub use parse::{ErrorSpan, ParseDiagnostic, ParseDiagnosticLabel, ParseDisplayLocation, ParseErrorInterpretation}; +pub(crate) use parse_diagnostics::interpret_parse_error; diff --git a/silverscript-lang/src/diagnostic/parse.rs b/silverscript-lang/src/diagnostic/parse.rs new file mode 100644 index 00000000..731a0551 --- /dev/null +++ b/silverscript-lang/src/diagnostic/parse.rs @@ -0,0 +1,217 @@ +use std::fmt; + +use pest::Position; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ErrorSpan { + pub start: usize, + pub end: usize, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum ParseErrorInterpretation { + MissingSemicolon, + Unclassified, +} + +impl ParseErrorInterpretation { + pub const fn code(self) -> &'static str { + match self { + Self::MissingSemicolon => "missing_semicolon", + Self::Unclassified => "parse_error", + } + } + + pub fn from_code(code: &str) -> Option { + match code { + "missing_semicolon" => Some(Self::MissingSemicolon), + "parse_error" => Some(Self::Unclassified), + _ => None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseDiagnosticLabel { + span: ErrorSpan, + message: String, +} + +impl ParseDiagnosticLabel { + pub fn new(span: ErrorSpan, message: impl Into) -> Self { + Self { span, message: message.into() } + } + + pub fn span(&self) -> ErrorSpan { + self.span + } + + pub fn message(&self) -> &str { + &self.message + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseDisplayLocation { + line: usize, + column: usize, + line_text: String, +} + +impl ParseDisplayLocation { + pub fn new(line: usize, column: usize, line_text: impl Into) -> Self { + Self { line, column, line_text: line_text.into() } + } + + pub fn line(&self) -> usize { + self.line + } + + pub fn column(&self) -> usize { + self.column + } + + pub fn line_text(&self) -> &str { + &self.line_text + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseDiagnostic { + interpretation: ParseErrorInterpretation, + span: ErrorSpan, + primary_message: String, + expected_tokens: Vec, + labels: Vec, + help: Option, + notes: Vec, + source_text: Box, +} + +impl ParseDiagnostic { + pub(crate) fn new( + interpretation: ParseErrorInterpretation, + span: ErrorSpan, + source_text: &str, + primary_message: impl Into, + ) -> Self { + Self { + interpretation, + span, + primary_message: primary_message.into(), + expected_tokens: Vec::new(), + labels: Vec::new(), + help: None, + notes: Vec::new(), + source_text: source_text.to_owned().into_boxed_str(), + } + } + + pub(crate) fn with_expected_tokens(mut self, expected_tokens: Vec) -> Self { + self.expected_tokens = expected_tokens; + self + } + + pub(crate) fn with_labels(mut self, labels: Vec) -> Self { + self.labels = labels; + self + } + + pub(crate) fn with_help(mut self, help: impl Into) -> Self { + self.help = Some(help.into()); + self + } + + pub(crate) fn with_notes(mut self, notes: Vec) -> Self { + self.notes = notes; + self + } + + pub fn code(&self) -> &'static str { + self.interpretation.code() + } + + pub fn interpretation(&self) -> ParseErrorInterpretation { + self.interpretation + } + + pub fn span(&self) -> ErrorSpan { + self.span + } + + pub fn primary_message(&self) -> &str { + &self.primary_message + } + + pub fn expected_tokens(&self) -> &[String] { + &self.expected_tokens + } + + pub fn labels(&self) -> &[ParseDiagnosticLabel] { + &self.labels + } + + pub fn help(&self) -> Option<&str> { + self.help.as_deref() + } + + pub fn notes(&self) -> &[String] { + &self.notes + } + + pub fn source_text(&self) -> &str { + &self.source_text + } + + pub fn display_location(&self) -> ParseDisplayLocation { + if self.source_text.is_empty() { + return ParseDisplayLocation::new(1, 1, String::new()); + } + let pos = self.span.start.min(self.source_text.len()); + let position = Position::new(&self.source_text, pos).unwrap_or_else(|| Position::from_start(&self.source_text)); + let (line, column) = position.line_col(); + let line_text = position.line_of().lines().next().unwrap_or_default().to_owned(); + ParseDisplayLocation::new(line, column, line_text) + } +} + +// TODO: make the display dumb and: +// * CLI: adapt diagnostic to miette diagnostic +// * LSP: adapt to LSP diagnostic (tower-lsp) +impl fmt::Display for ParseDiagnostic { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let location = self.display_location(); + let line_digits = location.line().to_string().len(); + let spacing = " ".repeat(line_digits); + let underline_pad = " ".repeat(location.column().saturating_sub(1)); + writeln!(f, "{spacing}--> {}:{}", location.line(), location.column())?; + writeln!(f, "{spacing} |")?; + writeln!(f, "{} | {}", location.line(), location.line_text())?; + writeln!(f, "{spacing} | {underline_pad}^---")?; + writeln!(f, "{spacing} |")?; + writeln!(f, "{spacing} = error: {}", self.primary_message)?; + + if !self.expected_tokens.is_empty() { + let expected_tokens = self.expected_tokens.iter().map(|token| format_expected_token(token)).collect::>().join(", "); + writeln!(f, "{spacing} note: expected one of tokens: {expected_tokens}")?; + } + for note in &self.notes { + writeln!(f, "{spacing} note: {note}")?; + } + if let Some(help) = &self.help { + writeln!(f, "{spacing} help: {help}")?; + } + + Ok(()) + } +} + +fn format_expected_token(token: &str) -> String { + match token { + "WHITESPACE" => "WHITESPACE".to_owned(), + _ => format!("`{token}`"), + } +} + +impl std::error::Error for ParseDiagnostic {} diff --git a/silverscript-lang/src/diagnostic/parse_diagnostics.rs b/silverscript-lang/src/diagnostic/parse_diagnostics.rs new file mode 100644 index 00000000..e24aa641 --- /dev/null +++ b/silverscript-lang/src/diagnostic/parse_diagnostics.rs @@ -0,0 +1,178 @@ +use std::collections::BTreeSet; + +use super::parse::{ErrorSpan, ParseDiagnostic, ParseDiagnosticLabel, ParseErrorInterpretation}; +use crate::parser::Rule; + +const MISSING_SEMICOLON_EXPECTED_TOKENS: &[&str] = &["WHITESPACE", "/*", "//", ";"]; + +#[derive(Clone, Copy)] +enum SpanStrategy { + AtFailure, + PreviousNonWhitespaceOrFailure, +} + +impl SpanStrategy { + fn resolve(self, input: &str, failure_pos: usize) -> ErrorSpan { + let failure_pos = failure_pos.min(input.len()); + let start = match self { + Self::AtFailure => failure_pos, + Self::PreviousNonWhitespaceOrFailure => focused_error_start(input, failure_pos), + }; + ErrorSpan { start, end: start } + } +} + +#[derive(Clone, Copy)] +struct InterpretationSpec { + interpretation: ParseErrorInterpretation, + span_strategy: SpanStrategy, + expected_tokens_override: Option<&'static [&'static str]>, + help: Option<&'static str>, + primary_label: Option<&'static str>, + notes: &'static [&'static str], +} + +const UNCLASSIFIED_SPEC: InterpretationSpec = InterpretationSpec { + interpretation: ParseErrorInterpretation::Unclassified, + span_strategy: SpanStrategy::AtFailure, + expected_tokens_override: None, + help: None, + primary_label: None, + notes: &[], +}; + +const INTERPRETATION_SPECS: &[InterpretationSpec] = &[ + InterpretationSpec { + interpretation: ParseErrorInterpretation::MissingSemicolon, + span_strategy: SpanStrategy::PreviousNonWhitespaceOrFailure, + expected_tokens_override: Some(MISSING_SEMICOLON_EXPECTED_TOKENS), + help: Some("statements must end with ';'"), + primary_label: Some("expected ';' to terminate statement"), + notes: &[], + }, + UNCLASSIFIED_SPEC, +]; + +#[derive(Clone, Copy)] +struct InterpretationHeuristic { + interpretation: ParseErrorInterpretation, + matches: fn(&ParseAttemptData) -> bool, +} + +const INTERPRETATION_HEURISTICS: &[InterpretationHeuristic] = + &[InterpretationHeuristic { interpretation: ParseErrorInterpretation::MissingSemicolon, matches: expects_semicolon }]; + +#[derive(Default)] +struct ParseAttemptData { + expected_tokens: Vec, + rules: Vec, +} + +impl ParseAttemptData { + fn from_error(err: &pest::error::Error) -> Self { + let Some(attempts) = err.parse_attempts() else { + return Self::default(); + }; + + let expected_tokens = attempts.expected_tokens().into_iter().map(|token| token.to_string()).collect::>(); + + let mut rules = Vec::new(); + for stack in attempts.call_stacks() { + if let Some(rule) = stack.deepest.get_rule() { + rules.push(*rule); + } + if let Some(rule) = stack.parent { + rules.push(rule); + } + } + + Self { expected_tokens, rules } + } + + fn expects_token(&self, token: &str) -> bool { + self.expected_tokens.iter().any(|candidate| candidate == token) + } + + // remove once used by one of the heuristic matcher + #[allow(dead_code)] + fn includes_rule(&self, rule: Rule) -> bool { + self.rules.contains(&rule) + } +} + +pub(crate) fn interpret_parse_error(input: &str, err: &pest::error::Error) -> ParseDiagnostic { + let failure_pos = error_start_offset(err); + let attempt_data = ParseAttemptData::from_error(err); + let interpretation = classify_interpretation(&attempt_data); + let spec = interpretation_spec(interpretation); + let span = spec.span_strategy.resolve(input, failure_pos); + let primary_message = match interpretation { + ParseErrorInterpretation::Unclassified => err.variant.message().into_owned(), + _ => "parsing error occurred.".to_owned(), + }; + + let mut diagnostic = ParseDiagnostic::new(interpretation, span, input, primary_message) + .with_expected_tokens(normalize_expected_tokens(&attempt_data.expected_tokens, spec)) + .with_labels(primary_labels(spec, span)) + .with_notes(spec.notes.iter().map(|note| (*note).to_owned()).collect()); + if let Some(help) = spec.help { + diagnostic = diagnostic.with_help(help); + } + diagnostic +} + +fn classify_interpretation(attempt_data: &ParseAttemptData) -> ParseErrorInterpretation { + INTERPRETATION_HEURISTICS + .iter() + .find(|heuristic| (heuristic.matches)(attempt_data)) + .map(|heuristic| heuristic.interpretation) + .unwrap_or(ParseErrorInterpretation::Unclassified) +} + +fn expects_semicolon(attempt_data: &ParseAttemptData) -> bool { + attempt_data.expects_token(";") +} + +fn interpretation_spec(interpretation: ParseErrorInterpretation) -> &'static InterpretationSpec { + INTERPRETATION_SPECS.iter().find(|spec| spec.interpretation == interpretation).unwrap_or(&UNCLASSIFIED_SPEC) +} + +fn normalize_expected_tokens(expected_tokens: &[String], spec: &InterpretationSpec) -> Vec { + if let Some(tokens) = spec.expected_tokens_override { + return tokens.iter().map(|token| (*token).to_owned()).collect(); + } + + expected_tokens.iter().map(|token| normalize_token(token)).collect::>().into_iter().collect() +} + +fn primary_labels(spec: &InterpretationSpec, span: ErrorSpan) -> Vec { + spec.primary_label.map(|label| vec![ParseDiagnosticLabel::new(span, label)]).unwrap_or_default() +} + +fn normalize_token(token: &str) -> String { + if token.chars().all(char::is_whitespace) { "WHITESPACE".to_string() } else { token.to_string() } +} + +fn error_start_offset(err: &pest::error::Error) -> usize { + match err.location { + pest::error::InputLocation::Pos(pos) => pos, + pest::error::InputLocation::Span((start, _)) => start, + } +} + +fn focused_error_start(input: &str, failure_pos: usize) -> usize { + if is_closing_delimiter_at(input, failure_pos) { + failure_pos + } else { + previous_non_whitespace_offset(input, failure_pos).unwrap_or(failure_pos) + } +} + +fn previous_non_whitespace_offset(input: &str, pos: usize) -> Option { + let prefix = input.get(..pos)?; + prefix.char_indices().rev().find_map(|(idx, ch)| if ch.is_whitespace() { None } else { Some(idx) }) +} + +fn is_closing_delimiter_at(input: &str, pos: usize) -> bool { + matches!(input.as_bytes().get(pos), Some(b')' | b']' | b'}')) +} diff --git a/silverscript-lang/src/errors.rs b/silverscript-lang/src/errors.rs new file mode 100644 index 00000000..caab450f --- /dev/null +++ b/silverscript-lang/src/errors.rs @@ -0,0 +1,52 @@ +use kaspa_txscript::script_builder::ScriptBuilderError; +use thiserror::Error; + +pub use crate::diagnostic::{ErrorSpan, ParseDiagnostic, ParseDiagnosticLabel, ParseDisplayLocation, ParseErrorInterpretation}; +use crate::span; + +#[derive(Debug, Error)] +pub enum CompilerError { + #[error("parse error: {0}")] + Parse(#[from] ParseDiagnostic), + #[error("unsupported feature: {0}")] + Unsupported(String), + #[error("invalid literal: {0}")] + InvalidLiteral(String), + #[error("undefined identifier: {0}")] + UndefinedIdentifier(String), + #[error("cyclic identifier reference: {0}")] + CyclicIdentifier(String), + #[error("script build error: {0}")] + ScriptBuild(#[from] ScriptBuilderError), + // QUESTION: not entierly sure about this pattern + #[error("{source}")] + Context { + #[source] + source: Box, + span: ErrorSpan, + }, +} + +impl CompilerError { + pub fn root(&self) -> &CompilerError { + let mut current = self; + while let Self::Context { source, .. } = current { + current = source; + } + current + } + + pub fn span(&self) -> Option { + match self { + Self::Context { span, .. } => Some(*span), + _ => None, + } + } + + pub fn with_span(self, span: &span::Span<'_>) -> Self { + if self.span().is_some() || matches!(self.root(), Self::Parse(_)) { + return self; + } + Self::Context { source: Box::new(self), span: ErrorSpan { start: span.start(), end: span.end() } } + } +} diff --git a/silverscript-lang/src/lib.rs b/silverscript-lang/src/lib.rs index abe745b8..60fb7e22 100644 --- a/silverscript-lang/src/lib.rs +++ b/silverscript-lang/src/lib.rs @@ -1,3 +1,6 @@ pub mod ast; pub mod compiler; +pub mod diagnostic; +pub mod errors; pub mod parser; +pub mod span; diff --git a/silverscript-lang/src/parser.rs b/silverscript-lang/src/parser.rs index 0ba10fa9..e00bd2ec 100644 --- a/silverscript-lang/src/parser.rs +++ b/silverscript-lang/src/parser.rs @@ -1,16 +1,24 @@ use pest::Parser; -use pest::error::Error; use pest::iterators::Pairs; use pest_derive::Parser; +use crate::errors::ParseDiagnostic; + #[derive(Parser)] #[grammar = "silverscript.pest"] pub struct SilverScriptParser; -pub fn parse_source_file(input: &str) -> Result, Error> { - SilverScriptParser::parse(Rule::source_file, input) +pub fn parse_source_file(input: &str) -> Result, ParseDiagnostic> { + pest::set_error_detail(true); + SilverScriptParser::parse(Rule::source_file, input).map_err(|err| crate::diagnostic::interpret_parse_error(input, &err)) +} + +pub fn parse_expression(input: &str) -> Result, ParseDiagnostic> { + pest::set_error_detail(true); + SilverScriptParser::parse(Rule::expression, input).map_err(|err| crate::diagnostic::interpret_parse_error(input, &err)) } -pub fn parse_expression(input: &str) -> Result, Error> { - SilverScriptParser::parse(Rule::expression, input) +pub fn parse_type_name(input: &str) -> Result, ParseDiagnostic> { + pest::set_error_detail(true); + SilverScriptParser::parse(Rule::type_name, input).map_err(|err| crate::diagnostic::interpret_parse_error(input, &err)) } diff --git a/silverscript-lang/src/span.rs b/silverscript-lang/src/span.rs new file mode 100644 index 00000000..00e415d9 --- /dev/null +++ b/silverscript-lang/src/span.rs @@ -0,0 +1,81 @@ +use std::fmt; +use std::ops::Deref; + +use pest::Span as PestSpan; +use serde::Serialize; +use serde::Serializer; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Span<'i>(PestSpan<'i>); + +impl<'i> Span<'i> { + pub fn new(input: &'i str, start: usize, end: usize) -> Option { + PestSpan::new(input, start, end).map(Span) + } + + pub fn join(&self, other: &Span<'i>) -> Span<'i> { + let input = self.get_input(); + let start = self.start().min(other.start()); + let end = self.end().max(other.end()); + Span::new(input, start, end).unwrap_or(*self) + } +} + +impl<'i> Default for Span<'i> { + fn default() -> Self { + Span(PestSpan::new("", 0, 0).expect("synthetic span")) + } +} + +impl<'i> From> for Span<'i> { + fn from(span: PestSpan<'i>) -> Self { + Span(span) + } +} + +impl<'i> Deref for Span<'i> { + type Target = PestSpan<'i>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'i> fmt::Display for Span<'i> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let source = self.as_str(); + if source.is_empty() { f.write_str("") } else { f.write_str(source) } + } +} + +// serde serialize becomes display +impl<'i> Serialize for Span<'i> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +pub trait SpanUtils { + fn len(&self) -> usize; + fn is_empty(&self) -> bool { + self.len() == 0 + } + fn contains(&self, offset: usize) -> bool; +} + +impl<'i> SpanUtils for Span<'i> { + fn len(&self) -> usize { + self.end().saturating_sub(self.start()) + } + + fn contains(&self, offset: usize) -> bool { + offset >= self.start() && offset < self.end() + } +} + +pub fn join<'i>(left: &Span<'i>, right: &Span<'i>) -> Span<'i> { + left.join(right) +} diff --git a/silverscript-lang/tests/ast_json/require_test.ast.json b/silverscript-lang/tests/ast_json/require_test.ast.json index fd35aa8b..0ead523d 100644 --- a/silverscript-lang/tests/ast_json/require_test.ast.json +++ b/silverscript-lang/tests/ast_json/require_test.ast.json @@ -1,7 +1,7 @@ { "name": "Test", "params": [], - "constants": {}, + "constants": [], "functions": [ { "name": "main", diff --git a/silverscript-lang/tests/ast_json/yield_test.ast.json b/silverscript-lang/tests/ast_json/yield_test.ast.json index 156c0cba..b93d70f0 100644 --- a/silverscript-lang/tests/ast_json/yield_test.ast.json +++ b/silverscript-lang/tests/ast_json/yield_test.ast.json @@ -1,7 +1,7 @@ { "name": "YieldTest", "params": [], - "constants": {}, + "constants": [], "functions": [ { "name": "main", diff --git a/silverscript-lang/tests/ast_json_tests.rs b/silverscript-lang/tests/ast_json_tests.rs index 115224c4..7d4dea28 100644 --- a/silverscript-lang/tests/ast_json_tests.rs +++ b/silverscript-lang/tests/ast_json_tests.rs @@ -3,7 +3,7 @@ use std::fs; use silverscript_lang::ast::ContractAst; use silverscript_lang::compiler::{CompileOptions, compile_contract, compile_contract_ast}; -fn load_ast(name: &str) -> ContractAst { +fn load_ast(name: &str) -> ContractAst<'_> { let path = format!("{}/tests/ast_json/{name}", env!("CARGO_MANIFEST_DIR")); let json = fs::read_to_string(&path).unwrap_or_else(|err| panic!("failed to read {path}: {err}")); serde_json::from_str(&json).unwrap_or_else(|err| panic!("failed to parse {path}: {err}")) diff --git a/silverscript-lang/tests/ast_spans_tests.rs b/silverscript-lang/tests/ast_spans_tests.rs new file mode 100644 index 00000000..0dca9faf --- /dev/null +++ b/silverscript-lang/tests/ast_spans_tests.rs @@ -0,0 +1,60 @@ +use silverscript_lang::ast::{ExprKind, Statement, parse_contract_ast}; + +fn assert_span_text(source: &str, actual: &str, expected: &str) { + let start = source.find(expected).expect("expected text must exist in source"); + let end = start + expected.len(); + assert_eq!(actual, expected); + assert_eq!(&source[start..end], expected); +} + +#[test] +fn populates_contract_function_and_statement_spans() { + let source = r#" + contract Foo(int a) { + function bar(int b):(int) { + int x = a + b; + return(x); + } + } + "#; + let contract = parse_contract_ast(source).expect("contract should parse"); + + assert_span_text(source, contract.name_span.as_str(), "Foo"); + assert_span_text(source, contract.functions[0].name_span.as_str(), "bar"); + assert_span_text(source, contract.functions[0].body_span.as_str(), "int x = a + b;\n return(x);"); + + let first_stmt = &contract.functions[0].body[0]; + let Statement::VariableDefinition { span, .. } = first_stmt else { + panic!("expected first statement to be a variable definition"); + }; + assert_span_text(source, span.as_str(), "int x = a + b;"); +} + +#[test] +fn populates_slice_expression_spans() { + let source = r#" + contract SliceTest() { + function main(byte[] data) { + byte[] part = data.slice(1, 3); + } + } + "#; + let contract = parse_contract_ast(source).expect("contract should parse"); + let stmt = &contract.functions[0].body[0]; + + let Statement::VariableDefinition { expr: Some(expr), .. } = stmt else { + panic!("expected a variable definition with expression"); + }; + let ExprKind::Slice { source: base, start, end, span } = &expr.kind else { + panic!("expected slice expression"); + }; + let ExprKind::Identifier(_) = &base.kind else { + panic!("slice source should be an identifier"); + }; + + assert_span_text(source, expr.span.as_str(), "data.slice(1, 3)"); + assert_span_text(source, span.as_str(), ".slice(1, 3)"); + assert_span_text(source, base.span.as_str(), "data"); + assert_span_text(source, start.span.as_str(), "1"); + assert_span_text(source, end.span.as_str(), "3"); +} diff --git a/silverscript-lang/tests/cashc_valid_examples_tests.rs b/silverscript-lang/tests/cashc_valid_examples_tests.rs index 43c43b2b..60e2b8b6 100644 --- a/silverscript-lang/tests/cashc_valid_examples_tests.rs +++ b/silverscript-lang/tests/cashc_valid_examples_tests.rs @@ -41,7 +41,7 @@ fn parse_contract_param_types(source: &str) -> Vec { result } -fn dummy_expr_for_type(type_name: &str) -> Expr { +fn dummy_expr_for_type(type_name: &str) -> Expr<'static> { if type_name == "int" { return 0i64.into(); } @@ -125,7 +125,7 @@ fn build_sigscript(args: &[ArgValue], selector: Option) -> Vec { builder.drain() } -fn selector_for_compiled(compiled: &CompiledContract, function_name: &str) -> Option { +fn selector_for_compiled(compiled: &CompiledContract<'_>, function_name: &str) -> Option { if compiled.without_selector { None } else { diff --git a/silverscript-lang/tests/compiler_tests.rs b/silverscript-lang/tests/compiler_tests.rs index 90ba77d3..e9f26528 100644 --- a/silverscript-lang/tests/compiler_tests.rs +++ b/silverscript-lang/tests/compiler_tests.rs @@ -126,15 +126,15 @@ fn accepts_constructor_args_with_matching_types() { } "#; let args = vec![ - Expr::Int(7), - Expr::Bool(true), - Expr::String("hello".to_string()), - vec![1u8; 10].into(), - Expr::Byte(2), // Single byte for type 'byte' - vec![3u8; 4].into(), - vec![4u8; 32].into(), - vec![5u8; 65].into(), - vec![6u8; 64].into(), + Expr::int(7), + Expr::bool(true), + Expr::string("hello".to_string()), + Expr::bytes(vec![1u8; 10]), + Expr::byte(2), + Expr::bytes(vec![3u8; 4]), + Expr::bytes(vec![4u8; 32]), + Expr::bytes(vec![5u8; 65]), + Expr::bytes(vec![6u8; 64]), ]; compile_contract(source, &args, CompileOptions::default()).expect("compile succeeds"); } @@ -148,7 +148,7 @@ fn rejects_constructor_args_with_wrong_scalar_types() { } } "#; - let args = vec![Expr::Bool(true), Expr::Int(1), vec![1u8].into()]; + let args = vec![Expr::bool(true), Expr::int(1), Expr::bytes(vec![1u8])]; assert!(compile_contract(source, &args, CompileOptions::default()).is_err()); } @@ -161,7 +161,13 @@ fn rejects_constructor_args_with_wrong_byte_lengths() { } } "#; - let args = vec![vec![1u8; 2].into(), vec![2u8; 3].into(), vec![3u8; 31].into(), vec![4u8; 63].into(), vec![5u8; 66].into()]; + let args = vec![ + Expr::bytes(vec![1u8; 2]), + Expr::bytes(vec![2u8; 3]), + Expr::bytes(vec![3u8; 31]), + Expr::bytes(vec![4u8; 63]), + Expr::bytes(vec![5u8; 66]), + ]; assert!(compile_contract(source, &args, CompileOptions::default()).is_err()); } @@ -194,7 +200,7 @@ fn accepts_constructor_args_with_any_bytes_length() { } } "#; - let args = vec![vec![9u8; 128].into()]; + let args = vec![Expr::bytes(vec![9u8; 128])]; compile_contract(source, &args, CompileOptions::default()).expect("compile succeeds"); } @@ -208,7 +214,7 @@ fn build_sig_script_builds_expected_script() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let args = vec![vec![1u8, 2, 3, 4].into(), Expr::Int(7)]; + let args = vec![Expr::bytes(vec![1u8, 2, 3, 4]), Expr::int(7)]; let sigscript = compiled.build_sig_script("spend", args).expect("sigscript builds"); let selector = selector_for(&compiled, "spend"); @@ -233,7 +239,7 @@ fn build_sig_script_rejects_unknown_function() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("missing", vec![Expr::Int(1)]); + let result = compiled.build_sig_script("missing", vec![Expr::int(1)]); assert!(result.is_err()); } @@ -247,7 +253,7 @@ fn build_sig_script_rejects_wrong_argument_count() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![Expr::Int(1)]); + let result = compiled.build_sig_script("spend", vec![Expr::int(1)]); assert!(result.is_err()); } @@ -261,7 +267,7 @@ fn build_sig_script_rejects_wrong_argument_type() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![vec![1u8; 3].into()]); + let result = compiled.build_sig_script("spend", vec![Expr::bytes(vec![1u8; 3])]); assert!(result.is_err()); } @@ -317,7 +323,7 @@ fn rejects_external_call_without_entrypoint() { "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("helper", vec![Expr::Int(1)]); + let result = compiled.build_sig_script("helper", vec![Expr::int(1)]); assert!(result.is_err()); } @@ -345,7 +351,7 @@ fn build_sig_script_rejects_mismatched_bytes_length() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![vec![1u8; 5].into()]); + let result = compiled.build_sig_script("spend", vec![Expr::bytes(vec![1u8; 5])]); assert!(result.is_err()); let source = r#" @@ -356,7 +362,7 @@ fn build_sig_script_rejects_mismatched_bytes_length() { } "#; let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); - let result = compiled.build_sig_script("spend", vec![vec![1u8; 4].into()]); + let result = compiled.build_sig_script("spend", vec![Expr::bytes(vec![1u8; 4])]); assert!(result.is_err()); } @@ -1389,7 +1395,7 @@ fn build_covenant_opcode_tx(sigscript: Vec, covenant_id_a: Hash, covenant_id (tx, entries) } -fn selector_for(compiled: &CompiledContract, function_name: &str) -> Option { +fn selector_for(compiled: &CompiledContract<'_>, function_name: &str) -> Option { if compiled.without_selector { None } else { @@ -3146,7 +3152,7 @@ fn compiles_script_size_and_runs_sum_array() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_size = compiled.script.len() as i64; - let sigscript = compiled.build_sig_script("main", vec![Expr::Int(expected_size)]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::int(expected_size)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "script size contract failed: {}", result.unwrap_err()); @@ -3173,7 +3179,7 @@ fn compiles_script_size_data_prefix_small_script() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_prefix = data_prefix_for_size(compiled.script.len()); - let sigscript = compiled.build_sig_script("main", vec![expected_prefix.into()]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::bytes(expected_prefix)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "scriptSizeDataPrefix small failed: {}", result.unwrap_err()); @@ -3194,7 +3200,7 @@ fn compiles_script_size_data_prefix_medium_script() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_prefix = data_prefix_for_size(compiled.script.len()); - let sigscript = compiled.build_sig_script("main", vec![expected_prefix.into()]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::bytes(expected_prefix)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "scriptSizeDataPrefix medium failed: {}", result.unwrap_err()); @@ -3215,7 +3221,7 @@ fn compiles_script_size_data_prefix_large_script() { let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); let expected_prefix = data_prefix_for_size(compiled.script.len()); - let sigscript = compiled.build_sig_script("main", vec![expected_prefix.into()]).expect("sigscript builds"); + let sigscript = compiled.build_sig_script("main", vec![Expr::bytes(expected_prefix)]).expect("sigscript builds"); let result = run_script_with_sigscript(compiled.script, sigscript); assert!(result.is_ok(), "scriptSizeDataPrefix large failed: {}", result.unwrap_err()); @@ -3506,3 +3512,62 @@ fn accepts_byte_array_with_constant_size() { "#; compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds with byte[HASH_SIZE]"); } + +#[test] +fn blake2b_int_and_byte_cast_forms_compile_to_identical_script() { + let source_plain = r#" + contract Test() { + entrypoint function test() { + int x = 5; + require(blake2b(x).length == 32); + } + } + "#; + + let source_cast = r#" + contract Test() { + entrypoint function test() { + int x = 5; + require(blake2b(byte[](x)).length == 32); + } + } + "#; + + let compiled_plain = compile_contract(source_plain, &[], CompileOptions::default()).expect("plain form compiles"); + let compiled_cast = compile_contract(source_cast, &[], CompileOptions::default()).expect("byte-cast form compiles"); + + assert_eq!( + compiled_plain.script, compiled_cast.script, + "blake2b(x) and blake2b(byte[](x)) should currently compile to identical scripts" + ); +} + +#[test] +fn empty_array_statement_expr_evaluation_compiles_to_empty_array_data() { + let source = r#" + contract Test() { + entrypoint function main() { + require([] == []); + } + } + "#; + + let compiled = compile_contract(source, &[], CompileOptions::default()).expect("compile succeeds"); + + let expected = ScriptBuilder::new() + .add_data(&[]) + .unwrap() + .add_data(&[]) + .unwrap() + .add_op(OpEqual) + .unwrap() + .add_op(OpVerify) + .unwrap() + .add_op(OpTrue) + .unwrap() + .drain(); + + assert_eq!(compiled.script, expected); + assert_eq!(compiled.script[0], OpFalse); + assert_eq!(compiled.script[1], OpFalse); +} diff --git a/silverscript-lang/tests/date_literal_tests.rs b/silverscript-lang/tests/date_literal_tests.rs index 1fef2c33..6b86d1db 100644 --- a/silverscript-lang/tests/date_literal_tests.rs +++ b/silverscript-lang/tests/date_literal_tests.rs @@ -1,7 +1,7 @@ use chrono::NaiveDateTime; -use silverscript_lang::ast::{Expr, Statement, parse_contract_ast}; +use silverscript_lang::ast::{Expr, ExprKind, Statement, parse_contract_ast}; -fn extract_first_expr(source: &str) -> Expr { +fn extract_first_expr<'i>(source: &'i str) -> Expr<'i> { let ast = parse_contract_ast(source).expect("parse succeeds"); let function = &ast.functions[0]; let statement = &function.body[0]; @@ -23,8 +23,8 @@ fn parses_date_literal_basic_iso() { } "#; let expr = extract_first_expr(source); - let Expr::Int(parsed) = expr else { - panic!("expected int literal"); + let Expr { kind: ExprKind::DateLiteral(parsed), .. } = expr else { + panic!("expected date literal"); }; let expected = NaiveDateTime::parse_from_str("2021-02-17T01:30:00", "%Y-%m-%dT%H:%M:%S").unwrap().and_utc().timestamp(); assert_eq!(parsed, expected); diff --git a/silverscript-lang/tests/parse_diagnostics_tests.rs b/silverscript-lang/tests/parse_diagnostics_tests.rs new file mode 100644 index 00000000..a0adf65a --- /dev/null +++ b/silverscript-lang/tests/parse_diagnostics_tests.rs @@ -0,0 +1,53 @@ +use silverscript_lang::ast::parse_contract_ast; +use silverscript_lang::errors::{CompilerError, ParseErrorInterpretation}; + +#[test] +fn full_diagnostic_from_missing_semicolon() { + let source = r#" + contract Foo() { + function bar(byte[] data) { + int x = a + b + int t = x + a; + } + } + "#; + let err = parse_contract_ast(source).expect_err("source without semicolon must fail parsing"); + let CompilerError::Parse(diagnostic) = err else { + panic!("expected parse error"); + }; + assert_eq!(diagnostic.interpretation(), ParseErrorInterpretation::MissingSemicolon); + assert_eq!(diagnostic.code(), "missing_semicolon"); + assert_eq!(diagnostic.expected_tokens(), ["WHITESPACE", "/*", "//", ";"]); + assert_eq!(diagnostic.primary_message(), "parsing error occurred."); + assert_eq!(diagnostic.help(), Some("statements must end with ';'")); + assert_eq!(diagnostic.labels().len(), 1); + + let span = diagnostic.span(); + assert_eq!(span.start, span.end); + assert_eq!(&source[span.start..span.start + 1], "b"); + + let location = diagnostic.display_location(); + assert!(location.line() > 0); + assert!(location.column() > 0); + assert!(location.line_text().contains("int x = a + b")); +} + +#[test] +fn unclassified_diagnostic_preserves_pest_message() { + let source = r#" + pragma silverscript ^0.1.0; + + contract Foo() { + ??? + } + "#; + + let err = parse_contract_ast(source).expect_err("invalid token must fail parsing"); + let CompilerError::Parse(diagnostic) = err else { + panic!("expected parse error"); + }; + + assert_eq!(diagnostic.interpretation(), ParseErrorInterpretation::Unclassified); + assert_ne!(diagnostic.primary_message(), "parsing error occurred."); + assert!(diagnostic.primary_message().contains("expected")); +} diff --git a/silverscript-lang/tests/parser_tests.rs b/silverscript-lang/tests/parser_tests.rs index 63cde999..f63ce1aa 100644 --- a/silverscript-lang/tests/parser_tests.rs +++ b/silverscript-lang/tests/parser_tests.rs @@ -50,3 +50,25 @@ fn parses_arrays_and_introspection() { panic!("{}", err); } } + +#[test] +fn parses_input_sigscript_and_rejects_output_sigscript() { + let input_ok = r#" + contract SigScriptCheck() { + function verify(int idx) { + require(tx.inputs[idx].sigScript.length >= 0); + } + } + "#; + assert!(parse_source_file(input_ok).is_ok()); + + let input_bad = r#" + contract SigScriptCheck() { + function verify(int idx) { + // outputs don't have a sigScript field, so parsing is expected to fail + require(tx.outputs[idx].sigScript.length >= 0); + } + } + "#; + assert!(parse_source_file(input_bad).is_err()); +} diff --git a/silverscript-lang/tests/silverc_tests.rs b/silverscript-lang/tests/silverc_tests.rs index 5f7ba4ef..eeb00a61 100644 --- a/silverscript-lang/tests/silverc_tests.rs +++ b/silverscript-lang/tests/silverc_tests.rs @@ -1,5 +1,5 @@ use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; use kaspa_consensus_core::hashing::sighash::SigHashReusedValuesUnsync; @@ -11,9 +11,38 @@ use kaspa_txscript::caches::Cache; use kaspa_txscript::script_builder::ScriptBuilder; use kaspa_txscript::{EngineCtx, EngineFlags, TxScriptEngine}; use rand::RngCore; -use silverscript_lang::ast::Expr; +use silverscript_lang::ast::{ContractAst, Expr}; use silverscript_lang::compiler::{CompiledContract, function_branch_index}; +const BASIC_CONTRACT_SOURCE: &str = r#" + contract Basic() { + entrypoint function main() { + require(true); + } + } + "#; + +const WITH_CTOR_SOURCE: &str = r#" + contract WithCtor(int a) { + entrypoint function main() { + require(a == 7); + } + } + "#; + +fn silverc() -> Command { + Command::new(env!("CARGO_BIN_EXE_silverc")) +} + +fn write_basic_contract(path: &Path) { + fs::write(path, BASIC_CONTRACT_SOURCE).expect("write source"); +} + +fn write_with_ctor_contract(path: &Path) { + fs::write(path, WITH_CTOR_SOURCE).expect("write source"); +} + +// TODO: move to tempfile crate or manually delete as a test tear down fn temp_dir(name: &str) -> PathBuf { let mut rng = rand::thread_rng(); let dir = std::env::temp_dir().join(format!("silverc_test_{name}_{}", rng.next_u64())); @@ -56,16 +85,9 @@ fn run_script_with_selector(script: Vec, selector: Option) -> Result<() fn silverc_defaults_output_path_and_empty_ctor_args() { let dir = temp_dir("default"); let src_path = dir.join("basic.sil"); - let source = r#" - contract Basic() { - entrypoint function main() { - require(true); - } - } - "#; - fs::write(&src_path, source).expect("write source"); + write_basic_contract(&src_path); - let status = Command::new(env!("CARGO_BIN_EXE_silverc")).arg(src_path.to_str().unwrap()).status().expect("run silverc"); + let status = silverc().arg(src_path.to_str().unwrap()).status().expect("run silverc"); assert!(status.success()); let out_path = dir.join("basic.json"); @@ -74,24 +96,32 @@ fn silverc_defaults_output_path_and_empty_ctor_args() { assert_eq!(compiled.contract_name, "Basic"); } +#[test] +fn silverc_stdout_flag_overrides_output_file() { + let dir = temp_dir("compile_stdout"); + let src_path = dir.join("basic.sil"); + let out_path = dir.join("compiled.json"); + write_basic_contract(&src_path); + + let output = + silverc().arg(src_path.to_str().unwrap()).arg("-o").arg(out_path.to_str().unwrap()).arg("-c").output().expect("run silverc"); + assert!(!output.status.success()); + + let stderr = String::from_utf8(output.stderr).expect("decode stderr"); + assert!(stderr.contains("invalid usage")); +} + #[test] fn silverc_accepts_constructor_args_and_output_flag() { let dir = temp_dir("ctor"); let src_path = dir.join("with_ctor.sil"); let out_path = dir.join("out.json"); let ctor_path = dir.join("ctor.json"); - let source = r#" - contract WithCtor(int a) { - entrypoint function main() { - require(a == 7); - } - } - "#; - fs::write(&src_path, source).expect("write source"); - let ctor_args = vec![Expr::Int(7)]; + write_with_ctor_contract(&src_path); + let ctor_args = vec![Expr::int(7)]; fs::write(&ctor_path, serde_json::to_string(&ctor_args).expect("serialize ctor args")).expect("write ctor args"); - let status = Command::new(env!("CARGO_BIN_EXE_silverc")) + let status = silverc() .arg(src_path.to_str().unwrap()) .arg("--constructor-args") .arg(ctor_path.to_str().unwrap()) @@ -108,3 +138,40 @@ fn silverc_accepts_constructor_args_and_output_flag() { if compiled.without_selector { None } else { Some(function_branch_index(&compiled.ast, "main").expect("selector resolved")) }; assert!(run_script_with_selector(compiled.script, selector).is_ok()); } + +#[test] +fn silverc_ast_only_defaults_to_file_with_suffix() { + let dir = temp_dir("ast"); + let src_path = dir.join("basic.sil"); + let out_path = dir.join("basic_ast.json"); + write_basic_contract(&src_path); + + let output = silverc().arg(src_path.to_str().unwrap()).arg("--ast-only").output().expect("run silverc"); + assert!(output.status.success()); + + let json = fs::read_to_string(&out_path).expect("read output"); + let ast: ContractAst<'static> = serde_json::from_str(&json).expect("parse ast json"); + assert_eq!(ast.name, "Basic"); +} + +#[test] +fn silverc_ast_only_writes_file_with_output_flag() { + let dir = temp_dir("ast_file"); + let src_path = dir.join("basic.sil"); + let out_path = dir.join("basic.ast.json"); + write_basic_contract(&src_path); + + let output = silverc() + .arg(src_path.to_str().unwrap()) + .arg("--ast-only") + .arg("-o") + .arg(out_path.to_str().unwrap()) + .output() + .expect("run silverc"); + assert!(output.status.success()); + assert!(output.stdout.is_empty()); + + let ast_json = fs::read_to_string(&out_path).expect("read ast output"); + let ast: ContractAst<'static> = serde_json::from_str(&ast_json).expect("parse ast json"); + assert_eq!(ast.name, "Basic"); +} diff --git a/silverscript-lang/tests/tutorial_rust_examples_tests.rs b/silverscript-lang/tests/tutorial_rust_examples_tests.rs index 146a14b1..2a8d2252 100644 --- a/silverscript-lang/tests/tutorial_rust_examples_tests.rs +++ b/silverscript-lang/tests/tutorial_rust_examples_tests.rs @@ -13,7 +13,7 @@ fn tutorial_rust_programmatic_compilation_example() { } "#; - let constructor_args = vec![Expr::Int(100)]; + let constructor_args = vec![Expr::int(100)]; let compiled = compile_contract(source, &constructor_args, CompileOptions::default()) .expect("programmatic compilation example should compile"); diff --git a/tree-sitter/.editorconfig b/tree-sitter/.editorconfig new file mode 100644 index 00000000..ff17b12f --- /dev/null +++ b/tree-sitter/.editorconfig @@ -0,0 +1,50 @@ +root = true + +[*] +charset = utf-8 + +[*.{json,toml,yml,gyp,xml}] +indent_style = space +indent_size = 2 + +[*.{js,ts}] +indent_style = space +indent_size = 2 + +[*.scm] +indent_style = space +indent_size = 2 + +[*.{c,cc,h}] +indent_style = space +indent_size = 4 + +[*.rs] +indent_style = space +indent_size = 4 + +[*.{py,pyi}] +indent_style = space +indent_size = 4 + +[*.swift] +indent_style = space +indent_size = 4 + +[*.java] +indent_style = space +indent_size = 4 + +[*.go] +indent_style = tab +indent_size = 8 + +[Makefile] +indent_style = tab +indent_size = 8 + +[parser.c] +indent_size = 2 + +[{alloc,array,parser}.h] +indent_size = 2 diff --git a/tree-sitter/.gitattributes b/tree-sitter/.gitattributes new file mode 100644 index 00000000..027ac707 --- /dev/null +++ b/tree-sitter/.gitattributes @@ -0,0 +1,46 @@ +* text=auto eol=lf + +# Generated source files +src/*.json linguist-generated +src/parser.c linguist-generated +src/tree_sitter/* linguist-generated + +# C bindings +bindings/c/** linguist-generated +CMakeLists.txt linguist-generated +Makefile linguist-generated + +# Rust bindings +bindings/rust/* linguist-generated +Cargo.toml linguist-generated +Cargo.lock linguist-generated + +# Node.js bindings +bindings/node/* linguist-generated +binding.gyp linguist-generated +package.json linguist-generated +package-lock.json linguist-generated + +# Python bindings +bindings/python/** linguist-generated +setup.py linguist-generated +pyproject.toml linguist-generated + +# Go bindings +bindings/go/* linguist-generated +go.mod linguist-generated +go.sum linguist-generated + +# Swift bindings +bindings/swift/** linguist-generated +Package.swift linguist-generated +Package.resolved linguist-generated + +# Zig bindings +bindings/zig/* linguist-generated +build.zig linguist-generated +build.zig.zon linguist-generated + +# Java bindings +pom.xml linguist-generated +bindings/java/** linguist-generated diff --git a/tree-sitter/.gitignore b/tree-sitter/.gitignore new file mode 100644 index 00000000..7c0cb7f5 --- /dev/null +++ b/tree-sitter/.gitignore @@ -0,0 +1,48 @@ +# Rust artifacts +target/ + +# Node artifacts +build/ +prebuilds/ +node_modules/ + +# Swift artifacts +.build/ + +# Go artifacts +_obj/ + +# Python artifacts +.venv/ +dist/ +*.egg-info +*.whl + +# C artifacts +*.a +*.so +*.so.* +*.dylib +*.dll +*.pc +*.exp +*.lib + +# Zig artifacts +.zig-cache/ +zig-cache/ +zig-out/ + +# Example dirs +/examples/*/ + +# Grammar volatiles +*.wasm +*.obj +*.o + +# Archives +*.tar.gz +*.tgz +*.zip +*.jar diff --git a/tree-sitter/CMakeLists.txt b/tree-sitter/CMakeLists.txt new file mode 100644 index 00000000..052a29c1 --- /dev/null +++ b/tree-sitter/CMakeLists.txt @@ -0,0 +1,76 @@ +cmake_minimum_required(VERSION 3.13) + +project(tree-sitter-silverscript + VERSION "0.1.0" + DESCRIPTION "Kaspa SilverScript Lang" + HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-silverscript" + LANGUAGES C) + +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF) + +set(TREE_SITTER_ABI_VERSION 15 CACHE STRING "Tree-sitter ABI version") +if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$") + unset(TREE_SITTER_ABI_VERSION CACHE) + message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer") +endif() + +include(GNUInstallDirs) + +find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI") + +add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" + "${CMAKE_CURRENT_SOURCE_DIR}/src/node-types.json" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/grammar.js" + COMMAND "${TREE_SITTER_CLI}" generate grammar.js --no-parser + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generating grammar.json") + +add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c" + BYPRODUCTS "${CMAKE_CURRENT_SOURCE_DIR}/src/tree_sitter/parser.h" + "${CMAKE_CURRENT_SOURCE_DIR}/src/tree_sitter/alloc.h" + "${CMAKE_CURRENT_SOURCE_DIR}/src/tree_sitter/array.h" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" + COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json + --abi=${TREE_SITTER_ABI_VERSION} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generating parser.c") + +add_library(tree-sitter-silverscript src/parser.c) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) + target_sources(tree-sitter-silverscript PRIVATE src/scanner.c) +endif() +target_include_directories(tree-sitter-silverscript + PRIVATE src + INTERFACE $ + $) + +target_compile_definitions(tree-sitter-silverscript PRIVATE + $<$:TREE_SITTER_REUSE_ALLOCATOR> + $<$:TREE_SITTER_DEBUG>) + +set_target_properties(tree-sitter-silverscript + PROPERTIES + C_STANDARD 11 + POSITION_INDEPENDENT_CODE ON + SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}" + DEFINE_SYMBOL "") + +configure_file(bindings/c/tree-sitter-silverscript.pc.in + "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-silverscript.pc" @ONLY) + +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + FILES_MATCHING PATTERN "*.h") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-silverscript.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +install(TARGETS tree-sitter-silverscript + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") + +file(GLOB QUERIES queries/*.scm) +install(FILES ${QUERIES} + DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries/silverscript") + +add_custom_target(ts-test "${TREE_SITTER_CLI}" test + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "tree-sitter test") diff --git a/tree-sitter/Cargo.lock b/tree-sitter/Cargo.lock new file mode 100644 index 00000000..77ee1d42 --- /dev/null +++ b/tree-sitter/Cargo.lock @@ -0,0 +1,216 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tree-sitter" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12987371f54efc9b9306a20dc87ed5aaee9f320c8a8b115e28515c412b2efe39" +dependencies = [ + "cc", + "regex", + "regex-syntax", + "serde_json", + "streaming-iterator", + "tree-sitter-language", +] + +[[package]] +name = "tree-sitter-language" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009994f150cc0cd50ff54917d5bc8bffe8cad10ca10d81c34da2ec421ae61782" + +[[package]] +name = "tree-sitter-silverscript" +version = "0.1.0" +dependencies = [ + "cc", + "tree-sitter", + "tree-sitter-language", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/tree-sitter/Cargo.toml b/tree-sitter/Cargo.toml new file mode 100644 index 00000000..ea1dfa66 --- /dev/null +++ b/tree-sitter/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "tree-sitter-silverscript" +description = "Kaspa SilverScript Lang" +version = "0.1.0" +authors = ["Kaspa Developers"] +license = "ISC" +readme = "README.md" +keywords = ["incremental", "parsing", "tree-sitter", "silverscript"] +categories = ["parser-implementations", "parsing", "text-editors"] +repository = "https://github.com/tree-sitter/tree-sitter-silverscript" +edition = "2021" +autoexamples = false + +build = "bindings/rust/build.rs" +include = [ + "bindings/rust/*", + "grammar.js", + "queries/*", + "src/*", + "tree-sitter.json", + "/LICENSE", +] + +[lib] +path = "bindings/rust/lib.rs" + +[dependencies] +tree-sitter-language = "0.1" + +[build-dependencies] +cc = "1.2" + +[dev-dependencies] +tree-sitter = "0.26.5" diff --git a/tree-sitter/Makefile b/tree-sitter/Makefile new file mode 100644 index 00000000..b3ed2498 --- /dev/null +++ b/tree-sitter/Makefile @@ -0,0 +1,115 @@ +LANGUAGE_NAME := tree-sitter-silverscript +HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-silverscript +VERSION := 0.1.0 + +# repository +SRC_DIR := src + +TS ?= tree-sitter + +# install directory layout +PREFIX ?= /usr/local +DATADIR ?= $(PREFIX)/share +INCLUDEDIR ?= $(PREFIX)/include +LIBDIR ?= $(PREFIX)/lib +BINDIR ?= $(PREFIX)/bin +PCLIBDIR ?= $(LIBDIR)/pkgconfig + +# source/object files +PARSER := $(SRC_DIR)/parser.c +EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) +OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) + +# flags +ARFLAGS ?= rcs +override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC + +# ABI versioning +SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) +SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) + +# OS-specific bits +MACHINE := $(shell $(CC) -dumpmachine) + +ifneq ($(findstring darwin,$(MACHINE)),) + SOEXT = dylib + SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) + SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) + LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks +else ifneq ($(findstring mingw32,$(MACHINE)),) + SOEXT = dll + LINKSHARED += -s -shared -Wl,--out-implib,lib$(LANGUAGE_NAME).dll.a +else + SOEXT = so + SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) + SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) + LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) +ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) + PCLIBDIR := $(PREFIX)/libdata/pkgconfig +endif +endif + +all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc + +lib$(LANGUAGE_NAME).a: $(OBJS) + $(AR) $(ARFLAGS) $@ $^ + +lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) + $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ +ifneq ($(STRIP),) + $(STRIP) $@ +endif + +ifneq ($(findstring mingw32,$(MACHINE)),) +lib$(LANGUAGE_NAME).dll.a: lib$(LANGUAGE_NAME).$(SOEXT) +endif + +$(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in + sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ + -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ + -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ + -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ + -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ + -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ + +$(SRC_DIR)/grammar.json: grammar.js + $(TS) generate --no-parser $^ + +$(PARSER): $(SRC_DIR)/grammar.json + $(TS) generate $^ + +install: all + install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/silverscript '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' + install -m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h + install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc + install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a + install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) +ifneq ($(findstring mingw32,$(MACHINE)),) + install -d '$(DESTDIR)$(BINDIR)' + install -m755 lib$(LANGUAGE_NAME).dll '$(DESTDIR)$(BINDIR)'/lib$(LANGUAGE_NAME).dll + install -m755 lib$(LANGUAGE_NAME).dll.a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).dll.a +else + install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) + cd '$(DESTDIR)$(LIBDIR)' && ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) + cd '$(DESTDIR)$(LIBDIR)' && ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) lib$(LANGUAGE_NAME).$(SOEXT) +endif +ifneq ($(wildcard queries/*.scm),) + install -m644 queries/*.scm '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/silverscript +endif + +uninstall: + $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ + '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ + '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ + '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ + '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ + '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc + $(RM) -r '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/silverscript + +clean: + $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) lib$(LANGUAGE_NAME).dll.a + +test: + $(TS) test + +.PHONY: all install uninstall clean test diff --git a/tree-sitter/Package.swift b/tree-sitter/Package.swift new file mode 100644 index 00000000..ebd2f39f --- /dev/null +++ b/tree-sitter/Package.swift @@ -0,0 +1,41 @@ +// swift-tools-version:5.3 + +import Foundation +import PackageDescription + +var sources = ["src/parser.c"] +if FileManager.default.fileExists(atPath: "src/scanner.c") { + sources.append("src/scanner.c") +} + +let package = Package( + name: "TreeSitterSilverscript", + products: [ + .library(name: "TreeSitterSilverscript", targets: ["TreeSitterSilverscript"]), + ], + dependencies: [ + .package(name: "SwiftTreeSitter", url: "https://github.com/tree-sitter/swift-tree-sitter", from: "0.9.0"), + ], + targets: [ + .target( + name: "TreeSitterSilverscript", + dependencies: [], + path: ".", + sources: sources, + resources: [ + .copy("queries") + ], + publicHeadersPath: "bindings/swift", + cSettings: [.headerSearchPath("src")] + ), + .testTarget( + name: "TreeSitterSilverscriptTests", + dependencies: [ + "SwiftTreeSitter", + "TreeSitterSilverscript", + ], + path: "bindings/swift/TreeSitterSilverscriptTests" + ) + ], + cLanguageStandard: .c11 +) diff --git a/tree-sitter/README.md b/tree-sitter/README.md new file mode 100644 index 00000000..77633bf6 --- /dev/null +++ b/tree-sitter/README.md @@ -0,0 +1,10 @@ +Attempt at being 1:1 with Pest. Interesting file: `tree-sitter\grammar.js`. + +- Install: `cargo install tree-sitter-cli --locked` +- Generate + sync highlights to editor extensions: `npm run generate` +- Build parser wasm (includes generate + sync): `npm run build` +- Standalone generate only: `npm run generate:raw` +- Standalone build only: `npm run build:raw` +- Open playground: `tree-sitter playground` + +- Grammar DSL Documentation: https://tree-sitter.github.io/tree-sitter/creating-parsers/2-the-grammar-dsl.html diff --git a/tree-sitter/binding.gyp b/tree-sitter/binding.gyp new file mode 100644 index 00000000..176cb11b --- /dev/null +++ b/tree-sitter/binding.gyp @@ -0,0 +1,35 @@ +{ + "targets": [ + { + "target_name": "tree_sitter_silverscript_binding", + "dependencies": [ + " + +typedef struct TSLanguage TSLanguage; + +extern "C" TSLanguage *tree_sitter_silverscript(); + +// "tree-sitter", "language" hashed with BLAKE2 +const napi_type_tag LANGUAGE_TYPE_TAG = { + 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 +}; + +Napi::Object Init(Napi::Env env, Napi::Object exports) { + auto language = Napi::External::New(env, tree_sitter_silverscript()); + language.TypeTag(&LANGUAGE_TYPE_TAG); + exports["language"] = language; + return exports; +} + +NODE_API_MODULE(tree_sitter_silverscript_binding, Init) diff --git a/tree-sitter/bindings/node/binding_test.js b/tree-sitter/bindings/node/binding_test.js new file mode 100644 index 00000000..7a91a84d --- /dev/null +++ b/tree-sitter/bindings/node/binding_test.js @@ -0,0 +1,11 @@ +import assert from "node:assert"; +import { test } from "node:test"; +import Parser from "tree-sitter"; + +test("can load grammar", () => { + const parser = new Parser(); + assert.doesNotReject(async () => { + const { default: language } = await import("./index.js"); + parser.setLanguage(language); + }); +}); diff --git a/tree-sitter/bindings/node/index.d.ts b/tree-sitter/bindings/node/index.d.ts new file mode 100644 index 00000000..87ff5f57 --- /dev/null +++ b/tree-sitter/bindings/node/index.d.ts @@ -0,0 +1,60 @@ +type BaseNode = { + type: string; + named: boolean; +}; + +type ChildNode = { + multiple: boolean; + required: boolean; + types: BaseNode[]; +}; + +type NodeInfo = + | (BaseNode & { + subtypes: BaseNode[]; + }) + | (BaseNode & { + fields: { [name: string]: ChildNode }; + children: ChildNode[]; + }); + +/** + * The tree-sitter language object for this grammar. + * + * @see {@linkcode https://tree-sitter.github.io/node-tree-sitter/interfaces/Parser.Language.html Parser.Language} + * + * @example + * import Parser from "tree-sitter"; + * import SilverScript from "tree-sitter-silverscript"; + * + * const parser = new Parser(); + * parser.setLanguage(SilverScript); + */ +declare const binding: { + /** + * The inner language object. + * @private + */ + language: unknown; + + /** + * The content of the `node-types.json` file for this grammar. + * + * @see {@linkplain https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types Static Node Types} + */ + nodeTypeInfo: NodeInfo[]; + + /** The syntax highlighting query for this grammar. */ + HIGHLIGHTS_QUERY?: string; + + /** The language injection query for this grammar. */ + INJECTIONS_QUERY?: string; + + /** The local variable query for this grammar. */ + LOCALS_QUERY?: string; + + /** The symbol tagging query for this grammar. */ + TAGS_QUERY?: string; +}; + +export default binding; diff --git a/tree-sitter/bindings/node/index.js b/tree-sitter/bindings/node/index.js new file mode 100644 index 00000000..4d29aa3a --- /dev/null +++ b/tree-sitter/bindings/node/index.js @@ -0,0 +1,42 @@ +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; + +const root = fileURLToPath(new URL("../..", import.meta.url)); + +const binding = + typeof process.versions.bun === "string" + ? // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time + await import( + `${root}/prebuilds/${process.platform}-${process.arch}/tree-sitter-silverscript.node` + ) + : (await import("node-gyp-build")).default(root); + +try { + const nodeTypes = await import(`${root}/src/node-types.json`, { + with: { type: "json" }, + }); + binding.nodeTypeInfo = nodeTypes.default; +} catch {} + +const queries = [ + ["HIGHLIGHTS_QUERY", `${root}/queries/highlights.scm`], + ["INJECTIONS_QUERY", `${root}/queries/injections.scm`], + ["LOCALS_QUERY", `${root}/queries/locals.scm`], + ["TAGS_QUERY", `${root}/queries/tags.scm`], +]; + +for (const [prop, path] of queries) { + Object.defineProperty(binding, prop, { + configurable: true, + enumerable: true, + get() { + delete binding[prop]; + try { + binding[prop] = readFileSync(path, "utf8"); + } catch {} + return binding[prop]; + }, + }); +} + +export default binding; diff --git a/tree-sitter/bindings/python/tests/test_binding.py b/tree-sitter/bindings/python/tests/test_binding.py new file mode 100644 index 00000000..ce1d8dbe --- /dev/null +++ b/tree-sitter/bindings/python/tests/test_binding.py @@ -0,0 +1,12 @@ +from unittest import TestCase + +from tree_sitter import Language, Parser +import tree_sitter_silverscript + + +class TestLanguage(TestCase): + def test_can_load_grammar(self): + try: + Parser(Language(tree_sitter_silverscript.language())) + except Exception: + self.fail("Error loading SilverScript grammar") diff --git a/tree-sitter/bindings/python/tree_sitter_silverscript/__init__.py b/tree-sitter/bindings/python/tree_sitter_silverscript/__init__.py new file mode 100644 index 00000000..1394c99e --- /dev/null +++ b/tree-sitter/bindings/python/tree_sitter_silverscript/__init__.py @@ -0,0 +1,54 @@ +"""Kaspa SilverScript Lang""" + +from importlib.resources import files as _files + +from ._binding import language + + +def _get_query(name, file): + try: + query = _files(f"{__package__}") / file + globals()[name] = query.read_text() + except FileNotFoundError: + globals()[name] = None + return globals()[name] + + +def __getattr__(name): + if name == "HIGHLIGHTS_QUERY": + return _get_query("HIGHLIGHTS_QUERY", "queries/highlights.scm") + if name == "INJECTIONS_QUERY": + return _get_query("INJECTIONS_QUERY", "queries/injections.scm") + if name == "LOCALS_QUERY": + return _get_query("LOCALS_QUERY", "queries/locals.scm") + if name == "TAGS_QUERY": + return _get_query("TAGS_QUERY", "queries/tags.scm") + + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +__all__ = [ + "language", + "HIGHLIGHTS_QUERY", + "INJECTIONS_QUERY", + "LOCALS_QUERY", + "TAGS_QUERY", +] + + +def __dir__(): + return sorted( + __all__ + + [ + "__all__", + "__builtins__", + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__path__", + "__spec__", + ] + ) diff --git a/tree-sitter/bindings/python/tree_sitter_silverscript/__init__.pyi b/tree-sitter/bindings/python/tree_sitter_silverscript/__init__.pyi new file mode 100644 index 00000000..5c88ff6c --- /dev/null +++ b/tree-sitter/bindings/python/tree_sitter_silverscript/__init__.pyi @@ -0,0 +1,17 @@ +from typing import Final +from typing_extensions import CapsuleType + +HIGHLIGHTS_QUERY: Final[str] | None +"""The syntax highlighting query for this grammar.""" + +INJECTIONS_QUERY: Final[str] | None +"""The language injection query for this grammar.""" + +LOCALS_QUERY: Final[str] | None +"""The local variable query for this grammar.""" + +TAGS_QUERY: Final[str] | None +"""The symbol tagging query for this grammar.""" + +def language() -> CapsuleType: + """The tree-sitter language function for this grammar.""" diff --git a/tree-sitter/bindings/python/tree_sitter_silverscript/binding.c b/tree-sitter/bindings/python/tree_sitter_silverscript/binding.c new file mode 100644 index 00000000..c6af4770 --- /dev/null +++ b/tree-sitter/bindings/python/tree_sitter_silverscript/binding.c @@ -0,0 +1,35 @@ +#include + +typedef struct TSLanguage TSLanguage; + +TSLanguage *tree_sitter_silverscript(void); + +static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { + return PyCapsule_New(tree_sitter_silverscript(), "tree_sitter.Language", NULL); +} + +static struct PyModuleDef_Slot slots[] = { +#ifdef Py_GIL_DISABLED + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, +#endif + {0, NULL} +}; + +static PyMethodDef methods[] = { + {"language", _binding_language, METH_NOARGS, + "Get the tree-sitter language for this grammar."}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef module = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_binding", + .m_doc = NULL, + .m_size = 0, + .m_methods = methods, + .m_slots = slots, +}; + +PyMODINIT_FUNC PyInit__binding(void) { + return PyModuleDef_Init(&module); +} diff --git a/tree-sitter/bindings/python/tree_sitter_silverscript/py.typed b/tree-sitter/bindings/python/tree_sitter_silverscript/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/tree-sitter/bindings/rust/build.rs b/tree-sitter/bindings/rust/build.rs new file mode 100644 index 00000000..c68f724b --- /dev/null +++ b/tree-sitter/bindings/rust/build.rs @@ -0,0 +1,50 @@ +fn main() { + let src_dir = std::path::Path::new("src"); + + let mut c_config = cc::Build::new(); + c_config.std("c11").include(src_dir); + + #[cfg(target_env = "msvc")] + c_config.flag("-utf-8"); + + if std::env::var("TARGET").unwrap() == "wasm32-unknown-unknown" { + let Ok(wasm_headers) = std::env::var("DEP_TREE_SITTER_LANGUAGE_WASM_HEADERS") else { + panic!("Environment variable DEP_TREE_SITTER_LANGUAGE_WASM_HEADERS must be set by the language crate"); + }; + let Ok(wasm_src) = std::env::var("DEP_TREE_SITTER_LANGUAGE_WASM_SRC").map(std::path::PathBuf::from) else { + panic!("Environment variable DEP_TREE_SITTER_LANGUAGE_WASM_SRC must be set by the language crate"); + }; + + c_config.include(&wasm_headers); + c_config.files([wasm_src.join("stdio.c"), wasm_src.join("stdlib.c"), wasm_src.join("string.c")]); + } + + let parser_path = src_dir.join("parser.c"); + c_config.file(&parser_path); + println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); + + let scanner_path = src_dir.join("scanner.c"); + if scanner_path.exists() { + c_config.file(&scanner_path); + println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); + } + + c_config.compile("tree-sitter-silverscript"); + + println!("cargo:rustc-check-cfg=cfg(with_highlights_query)"); + if !"queries/highlights.scm".is_empty() && std::path::Path::new("queries/highlights.scm").exists() { + println!("cargo:rustc-cfg=with_highlights_query"); + } + println!("cargo:rustc-check-cfg=cfg(with_injections_query)"); + if !"queries/injections.scm".is_empty() && std::path::Path::new("queries/injections.scm").exists() { + println!("cargo:rustc-cfg=with_injections_query"); + } + println!("cargo:rustc-check-cfg=cfg(with_locals_query)"); + if !"queries/locals.scm".is_empty() && std::path::Path::new("queries/locals.scm").exists() { + println!("cargo:rustc-cfg=with_locals_query"); + } + println!("cargo:rustc-check-cfg=cfg(with_tags_query)"); + if !"queries/tags.scm".is_empty() && std::path::Path::new("queries/tags.scm").exists() { + println!("cargo:rustc-cfg=with_tags_query"); + } +} diff --git a/tree-sitter/bindings/rust/lib.rs b/tree-sitter/bindings/rust/lib.rs new file mode 100644 index 00000000..96918738 --- /dev/null +++ b/tree-sitter/bindings/rust/lib.rs @@ -0,0 +1,59 @@ +//! This crate provides SilverScript language support for the [tree-sitter] parsing library. +//! +//! Typically, you will use the [`LANGUAGE`] constant to add this language to a +//! tree-sitter [`Parser`], and then use the parser to parse some code: +//! +//! ``` +//! let code = r#" +//! contract Demo() {} +//! "#; +//! let mut parser = tree_sitter::Parser::new(); +//! let language = tree_sitter_silverscript::LANGUAGE; +//! parser +//! .set_language(&language.into()) +//! .expect("Error loading SilverScript parser"); +//! let tree = parser.parse(code, None).unwrap(); +//! assert!(!tree.root_node().has_error()); +//! ``` +//! +//! [`Parser`]: https://docs.rs/tree-sitter/0.26.3/tree_sitter/struct.Parser.html +//! [tree-sitter]: https://tree-sitter.github.io/ + +use tree_sitter_language::LanguageFn; + +extern "C" { + fn tree_sitter_silverscript() -> *const (); +} + +/// The tree-sitter [`LanguageFn`] for this grammar. +pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_silverscript) }; + +/// The content of the [`node-types.json`] file for this grammar. +/// +/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types +pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); + +#[cfg(with_highlights_query)] +/// The syntax highlighting query for this grammar. +pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); + +#[cfg(with_injections_query)] +/// The language injection query for this grammar. +pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm"); + +#[cfg(with_locals_query)] +/// The local variable query for this grammar. +pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm"); + +#[cfg(with_tags_query)] +/// The symbol tagging query for this grammar. +pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm"); + +#[cfg(test)] +mod tests { + #[test] + fn test_can_load_grammar() { + let mut parser = tree_sitter::Parser::new(); + parser.set_language(&super::LANGUAGE.into()).expect("Error loading SilverScript parser"); + } +} diff --git a/tree-sitter/bindings/swift/TreeSitterSilverscript/silverscript.h b/tree-sitter/bindings/swift/TreeSitterSilverscript/silverscript.h new file mode 100644 index 00000000..93fd2f22 --- /dev/null +++ b/tree-sitter/bindings/swift/TreeSitterSilverscript/silverscript.h @@ -0,0 +1,16 @@ +#ifndef TREE_SITTER_SILVERSCRIPT_H_ +#define TREE_SITTER_SILVERSCRIPT_H_ + +typedef struct TSLanguage TSLanguage; + +#ifdef __cplusplus +extern "C" { +#endif + +const TSLanguage *tree_sitter_silverscript(void); + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_SILVERSCRIPT_H_ diff --git a/tree-sitter/bindings/swift/TreeSitterSilverscriptTests/TreeSitterSilverscriptTests.swift b/tree-sitter/bindings/swift/TreeSitterSilverscriptTests/TreeSitterSilverscriptTests.swift new file mode 100644 index 00000000..9301d750 --- /dev/null +++ b/tree-sitter/bindings/swift/TreeSitterSilverscriptTests/TreeSitterSilverscriptTests.swift @@ -0,0 +1,12 @@ +import XCTest +import SwiftTreeSitter +import TreeSitterSilverscript + +final class TreeSitterSilverscriptTests: XCTestCase { + func testCanLoadGrammar() throws { + let parser = Parser() + let language = Language(language: tree_sitter_silverscript()) + XCTAssertNoThrow(try parser.setLanguage(language), + "Error loading SilverScript grammar") + } +} diff --git a/tree-sitter/go.mod b/tree-sitter/go.mod new file mode 100644 index 00000000..147c5236 --- /dev/null +++ b/tree-sitter/go.mod @@ -0,0 +1,5 @@ +module github.com/tree-sitter/tree-sitter-silverscript + +go 1.22 + +require github.com/tree-sitter/go-tree-sitter v0.24.0 diff --git a/tree-sitter/grammar.js b/tree-sitter/grammar.js new file mode 100644 index 00000000..9b9ff459 --- /dev/null +++ b/tree-sitter/grammar.js @@ -0,0 +1,438 @@ +/** + * @file Kaspa SilverScript Lang + * @author Kaspa Developers + * @license ISC + */ + +/// +// @ts-check + +const PREC = { + LOGICAL_OR: 1, + LOGICAL_AND: 2, + BIT_OR: 3, + BIT_XOR: 4, + BIT_AND: 5, + EQUALITY: 6, + COMPARISON: 7, + TERM: 8, + FACTOR: 9, + UNARY: 10, + POSTFIX: 11, +}; + +export default grammar({ + name: "silverscript", + + extras: ($) => [/\s/, $.comment], + + word: ($) => $.identifier, + + rules: { + source_file: ($) => seq(repeat($.pragma_directive), $.contract_definition), + + pragma_directive: ($) => seq("pragma", "silverscript", $.pragma_value, ";"), + + pragma_value: ($) => + seq($.version_constraint, optional($.version_constraint)), + + version_constraint: ($) => + seq(optional($.version_operator), $.version_literal), + + version_operator: (_) => choice("^", "~", ">=", ">", "<=", "<", "="), + + version_literal: (_) => token(/\d+\.\d+\.\d+/), + + contract_definition: ($) => + seq( + "contract", + field("name", $.identifier), + $.parameter_list, + "{", + repeat($.contract_item), + "}", + ), + + contract_item: ($) => + choice( + $.constant_definition, + $.contract_field_definition, + $.function_definition, + ), + + function_definition: ($) => + seq( + optional("entrypoint"), + "function", + field("name", $.identifier), + $.parameter_list, + optional($.return_type_list), + "{", + repeat($.statement), + "}", + ), + + constant_definition: ($) => + seq( + $.type_name, + "constant", + field("name", $.identifier), + "=", + field("value", $.expression), + ";", + ), + + contract_field_definition: ($) => + seq( + $.type_name, + field("name", $.identifier), + "=", + field("value", $.expression), + ";", + ), + + parameter_list: ($) => seq("(", optional(commaSep($.parameter)), ")"), + + parameter: ($) => seq($.type_name, $.identifier), + + return_type_list: ($) => + seq(":", "(", optional(commaSep($.type_name)), ")"), + + block: ($) => choice(seq("{", repeat($.statement), "}"), $.statement), + + statement: ($) => + choice( + $.variable_definition, + $.tuple_assignment, + $.push_statement, + $.state_function_call_assignment, + $.function_call_assignment, + $.call_statement, + $.return_statement, + $.assign_statement, + $.time_op_statement, + $.require_statement, + $.if_statement, + $.for_statement, + $.yield_statement, + $.console_statement, + ), + + variable_definition: ($) => + seq( + $.type_name, + repeat($.modifier), + field("name", $.identifier), + optional(seq("=", field("value", $.expression))), + ";", + ), + + tuple_assignment: ($) => + seq( + $.type_name, + $.identifier, + ",", + $.type_name, + $.identifier, + "=", + $.expression, + ";", + ), + + push_statement: ($) => + seq(field("name", $.identifier), ".push", "(", $.expression, ")", ";"), + + function_call_assignment: ($) => + seq("(", commaSep($.typed_binding), ")", "=", $.function_call, ";"), + + state_function_call_assignment: ($) => + seq("{", commaSep($.state_typed_binding), "}", "=", $.function_call, ";"), + + typed_binding: ($) => seq($.type_name, $.identifier), + + state_typed_binding: ($) => + seq($.identifier, ":", $.type_name, $.identifier), + + call_statement: ($) => seq($.function_call, ";"), + + return_statement: ($) => seq("return", $.expression_list, ";"), + + assign_statement: ($) => + seq(field("name", $.identifier), "=", field("value", $.expression), ";"), + + time_op_statement: ($) => + seq( + "require", + "(", + $.tx_var, + ">=", + $.expression, + optional(seq(",", $.require_message)), + ")", + ";", + ), + + require_statement: ($) => + seq( + "require", + "(", + $.expression, + optional(seq(",", $.require_message)), + ")", + ";", + ), + + require_message: ($) => $.string_literal, + + if_statement: ($) => + prec.right( + seq( + "if", + "(", + $.expression, + ")", + $.block, + optional(seq("else", $.block)), + ), + ), + + for_statement: ($) => + seq( + "for", + "(", + $.identifier, + ",", + $.expression, + ",", + $.expression, + ")", + $.block, + ), + + yield_statement: ($) => seq("yield", $.expression_list, ";"), + + console_statement: ($) => seq("console.log", $.console_parameter_list, ";"), + + console_parameter_list: ($) => + seq("(", optional(commaSep($.console_parameter)), ")"), + + console_parameter: ($) => choice($.identifier, $.literal), + + expression: ($) => $.logical_or, + + logical_or: ($) => + prec.left( + PREC.LOGICAL_OR, + seq($.logical_and, repeat(seq("||", $.logical_and))), + ), + + logical_and: ($) => + prec.left(PREC.LOGICAL_AND, seq($.bit_or, repeat(seq("&&", $.bit_or)))), + + bit_or: ($) => + prec.left(PREC.BIT_OR, seq($.bit_xor, repeat(seq("|", $.bit_xor)))), + + bit_xor: ($) => + prec.left(PREC.BIT_XOR, seq($.bit_and, repeat(seq("^", $.bit_and)))), + + bit_and: ($) => + prec.left(PREC.BIT_AND, seq($.equality, repeat(seq("&", $.equality)))), + + equality: ($) => + prec.left( + PREC.EQUALITY, + seq($.comparison, repeat(seq(choice("==", "!="), $.comparison))), + ), + + comparison: ($) => + prec.left( + PREC.COMPARISON, + seq($.term, repeat(seq(choice("<=", "<", ">=", ">"), $.term))), + ), + + term: ($) => + prec.left( + PREC.TERM, + seq($.factor, repeat(seq(choice("+", "-"), $.factor))), + ), + + factor: ($) => + prec.left( + PREC.FACTOR, + seq($.unary, repeat(seq(choice("*", "/", "%"), $.unary))), + ), + + unary: ($) => prec.right(PREC.UNARY, seq(repeat($.unary_op), $.postfix)), + + unary_op: (_) => choice("!", "-"), + + postfix: ($) => + prec.left(PREC.POSTFIX, seq($.primary, repeat($.postfix_op))), + + postfix_op: ($) => + choice( + $.tuple_index, + $.unary_suffix, + $.split_call, + $.slice_call, + $.reverse_call, + ), + + tuple_index: ($) => seq("[", $.expression, "]"), + + unary_suffix: (_) => ".length", + + split_call: ($) => seq(".split", "(", $.expression, ")"), + + slice_call: ($) => seq(".slice", "(", $.expression, ",", $.expression, ")"), + + reverse_call: (_) => seq(".reverse", "(", ")"), + + primary: ($) => + choice( + $.parenthesized, + $.cast, + $.function_call, + $.instantiation, + $.state_object, + $.introspection, + $.array, + $.nullary_op, + $.identifier, + $.literal, + ), + + parenthesized: ($) => seq("(", $.expression, ")"), + + // type_name("(" expression ("," expression)? ","? ")" + cast: ($) => + seq( + $.type_name, + "(", + $.expression, + optional(seq(",", $.expression)), + optional(","), + ")", + ), + + function_call: ($) => seq($.identifier, $.expression_list), + + expression_list: ($) => seq("(", optional(commaSep($.expression)), ")"), + + instantiation: ($) => seq("new", $.identifier, $.expression_list), + + state_object: ($) => seq("{", optional(commaSep($.state_entry)), "}"), + + state_entry: ($) => seq($.identifier, ":", $.expression), + + introspection: ($) => + choice( + seq( + field("root", $.output_root), + field("index", $.tuple_index), + field("field", $.output_field), + ), + seq( + field("root", $.input_root), + field("index", $.tuple_index), + field("field", $.input_field), + ), + ), + + output_root: (_) => "tx.outputs", + + input_root: (_) => "tx.inputs", + + output_field: ($) => seq(".", field("name", $.output_field_name)), + + output_field_name: (_) => choice("value", "scriptPubKey"), + + input_field: ($) => seq(".", field("name", $.input_field_name)), + + input_field_name: (_) => + choice( + "value", + "scriptPubKey", + "outpointTransactionHash", + "outpointIndex", + "sigScript", + ), + + array: ($) => seq("[", optional(commaSep($.expression)), "]"), + + modifier: (_) => "constant", + + type_name: ($) => seq($.base_type, repeat($.array_suffix)), + + base_type: (_) => + choice("int", "bool", "string", "pubkey", "sig", "datasig", "byte"), + + array_suffix: ($) => seq("[", optional($.array_size), "]"), + + array_size: ($) => choice($.identifier, $.array_bound), + + array_bound: (_) => token(/[1-9][0-9]*/), + + literal: ($) => + choice( + $.boolean_literal, + $.number_literal, + $.string_literal, + $.date_literal, + $.hex_literal, + ), + + boolean_literal: (_) => choice("true", "false"), + + number_literal: ($) => seq($.number, optional($.number_unit)), + + number_unit: (_) => + choice( + "litras", + "grains", + "kas", + "seconds", + "minutes", + "hours", + "days", + "weeks", + ), + + // Pest: NumberLiteral = "-"? NumberPart ExponentPart? + number: (_) => token(/-?\d+(?:_\d+)*(?:[eE]\d+(?:_\d+)*)?/), + + string_literal: (_) => + token(choice(/"([^"\\\n]|\\.)*"/, /'([^'\\\n]|\\.)*'/)), + + date_literal: ($) => seq("date", "(", $.string_literal, ")"), + + hex_literal: (_) => token(/0[xX][0-9a-fA-F]*/), + + tx_var: (_) => choice("this.age", "tx.time"), + + nullary_op: (_) => + choice( + "this.activeInputIndex", + "this.activeScriptPubKey", + "this.scriptSizeDataPrefix", + "this.scriptSize", + "tx.inputs.length", + "tx.outputs.length", + "tx.version", + "tx.locktime", + ), + + identifier: (_) => token(prec(-1, /[A-Za-z][A-Za-z0-9_]*/)), + + comment: (_) => + token(choice(/\/\/[^\n]*/, /\/\*[^*]*\*+([^/*][^*]*\*+)*\//)), + }, +}); + +// item ("," item)* ","? +/** + * @param {RuleOrLiteral} rule + */ +function commaSep(rule) { + return seq(rule, repeat(seq(",", rule)), optional(",")); +} diff --git a/tree-sitter/package-lock.json b/tree-sitter/package-lock.json new file mode 100644 index 00000000..7242e2a5 --- /dev/null +++ b/tree-sitter/package-lock.json @@ -0,0 +1,382 @@ +{ + "name": "tree-sitter-silverscript", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tree-sitter-silverscript", + "version": "0.1.0", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "node-addon-api": "8.5.0", + "node-gyp-build": "4.8.4" + }, + "devDependencies": { + "prebuildify": "6.0.1", + "tree-sitter": "0.25.0", + "tree-sitter-cli": "0.26.5" + }, + "peerDependencies": { + "tree-sitter": "0.25.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/npm-run-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/prebuildify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/prebuildify/-/prebuildify-6.0.1.tgz", + "integrity": "sha512-8Y2oOOateom/s8dNBsGIcnm6AxPmLH4/nanQzL5lQMU+sC0CMhzARZHizwr36pUPLdvBnOkCNQzxg4djuFSgIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "mkdirp-classic": "^0.5.3", + "node-abi": "^3.3.0", + "npm-run-path": "^3.1.0", + "pump": "^3.0.0", + "tar-fs": "^2.1.0" + }, + "bin": { + "prebuildify": "bin.js" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tree-sitter": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.25.0.tgz", + "integrity": "sha512-PGZZzFW63eElZJDe/b/R/LbsjDDYJa5UEjLZJB59RQsMX+fo0j54fqBPn1MGKav/QNa0JR0zBiVaikYDWCj5KQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + } + }, + "node_modules/tree-sitter-cli": { + "version": "0.26.5", + "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.26.5.tgz", + "integrity": "sha512-joGY67M2XUVM+ZEs7vTYmSbiDgxtwbuMf1OdKk8q1Dd6wTlbhgtU/mr3j0krBgQs2Zwom6N7vxZaqoM85b79Mw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "tree-sitter": "cli.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/tree-sitter/package.json b/tree-sitter/package.json new file mode 100644 index 00000000..5d7f1097 --- /dev/null +++ b/tree-sitter/package.json @@ -0,0 +1,64 @@ +{ + "name": "tree-sitter-silverscript", + "version": "0.1.0", + "description": "Kaspa SilverScript Lang", + "type": "module", + "repository": { + "type": "git", + "url": "https://github.com/kaspanet/silverscript.git" + }, + "license": "ISC", + "author": { + "name": "Kaspa Developers" + }, + "main": "bindings/node", + "types": "bindings/node", + "keywords": [ + "incremental", + "parsing", + "tree-sitter", + "silverscript" + ], + "files": [ + "grammar.js", + "tree-sitter.json", + "binding.gyp", + "prebuilds/**", + "bindings/node/*", + "queries/*", + "src/**", + "*.wasm" + ], + "dependencies": { + "node-addon-api": "8.5.0", + "node-gyp-build": "4.8.4" + }, + "devDependencies": { + "prebuildify": "6.0.1", + "tree-sitter": "0.25.0", + "tree-sitter-cli": "0.26.5" + }, + "peerDependencies": { + "tree-sitter": "0.25.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + }, + "scripts": { + "install": "node-gyp-build", + "sync:highlights": "node scripts/sync-highlights.mjs", + "sync:zed-wasm": "node scripts/sync-zed-wasm.mjs", + "sync:vscode-wasm": "node scripts/sync-vscode-wasm.mjs", + "generate": "npm run generate:raw && npm run sync:highlights", + "generate:raw": "tree-sitter generate", + "build": "npm run generate && npm run build:raw", + "build:zed": "npm run build && npm run sync:zed-wasm", + "build:vscode": "npm run build && npm run sync:vscode-wasm", + "build:raw": "tree-sitter build --wasm", + "prestart": "npm run build", + "start": "tree-sitter playground", + "test": "node --test bindings/node/*_test.js" + } +} diff --git a/tree-sitter/pyproject.toml b/tree-sitter/pyproject.toml new file mode 100644 index 00000000..272b4bf5 --- /dev/null +++ b/tree-sitter/pyproject.toml @@ -0,0 +1,30 @@ +[build-system] +requires = ["setuptools>=62.4.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "tree-sitter-silverscript" +description = "Kaspa SilverScript Lang" +version = "0.1.0" +keywords = ["incremental", "parsing", "tree-sitter", "silverscript"] +classifiers = [ + "Intended Audience :: Developers", + "Topic :: Software Development :: Compilers", + "Topic :: Text Processing :: Linguistic", + "Typing :: Typed", +] +authors = [{ name = "Kaspa Developers" }] +requires-python = ">=3.10" +license.text = "ISC" +readme = "README.md" + +[project.urls] +Homepage = "https://github.com/tree-sitter/tree-sitter-silverscript" +Funding = "" + +[project.optional-dependencies] +core = ["tree-sitter~=0.24"] + +[tool.cibuildwheel] +build = "cp310-*" +build-frontend = "build" diff --git a/tree-sitter/queries/highlights.scm b/tree-sitter/queries/highlights.scm new file mode 100644 index 00000000..d730b378 --- /dev/null +++ b/tree-sitter/queries/highlights.scm @@ -0,0 +1,126 @@ +(comment) @comment + +(string_literal) @string + +(number_literal) @number + +(hex_literal) @number + +(boolean_literal) @boolean + +(date_literal) @function.builtin + +(type_name) @type + +(instantiation + (identifier) @type.builtin + (#match? @type.builtin + "^(LockingBytecodeNullData|ScriptPubKeyP2PK|ScriptPubKeyP2SH|ScriptPubKeyP2SHFromRedeemScript)$")) + +(instantiation + (identifier) @type) + +(contract_definition + name: (identifier) @type) + +(function_definition + name: (identifier) @function) + +(constant_definition + name: (identifier) @constant) + +(contract_field_definition + name: (identifier) @property) + +(variable_definition + name: (identifier) @variable) + +(parameter + (identifier) @variable.parameter) + +(tx_var) @variable.builtin + +(nullary_op) @variable.builtin + +(output_root) @variable.builtin + +(input_root) @variable.builtin + +(tuple_index + "[" @operator + "]" @operator) + +(output_field + "." @operator) + +(input_field + "." @operator) + +(output_field_name) @property + +(input_field_name) @property + +(state_entry + (identifier) @property) + +(state_typed_binding + (identifier) @property + ":" + (type_name) + (identifier) @variable) + +(function_call + (identifier) @function.builtin + (#match? @function.builtin + "^(readInputState|validateOutputState|verifyOutputState|verifyOutputStates|OpSha256|sha256|OpTxSubnetId|OpTxGas|OpTxPayloadLen|OpTxPayloadSubstr|OpOutpointTxId|OpOutpointIndex|OpTxInputScriptSigLen|OpTxInputScriptSigSubstr|OpTxInputSeq|OpTxInputIsCoinbase|OpTxInputSpkLen|OpTxInputSpkSubstr|OpTxOutputSpkLen|OpTxOutputSpkSubstr|OpAuthOutputCount|OpAuthOutputIdx|OpInputCovenantId|OpCovInputCount|OpCovInputIdx|OpCovOutCount|OpCovOutputIdx|OpNum2Bin|OpBin2Num|OpChainblockSeqCommit|checkDataSig|checkSig|checkMultiSig|blake2b)$")) + +(unary_suffix) @property + +(split_call + ".split" @function.method) + +(slice_call + ".slice" @function.method) + +(reverse_call + ".reverse" @function.method) + +(array_bound) @number + +[ + "pragma" + "silverscript" + "contract" + "entrypoint" + "function" + "constant" + "if" + "else" + "for" + "new" + "require" + "return" + "yield" + "console.log" +] @keyword + +[ + "||" + "&&" + "==" + "!=" + "<" + "<=" + ">" + ">=" + "+" + "-" + "*" + "/" + "%" + "!" + "&" + "|" + "^" + "=" +] @operator diff --git a/tree-sitter/scripts/sync-highlights.mjs b/tree-sitter/scripts/sync-highlights.mjs new file mode 100644 index 00000000..f2c0d9dc --- /dev/null +++ b/tree-sitter/scripts/sync-highlights.mjs @@ -0,0 +1,44 @@ +#!/usr/bin/env node + +import { copyFile, mkdir } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); +const treeSitterDir = path.resolve(scriptDir, ".."); +const repoRoot = path.resolve(treeSitterDir, ".."); + +const source = path.join(treeSitterDir, "queries", "highlights.scm"); +const targets = [ + path.join(repoRoot, "extensions", "vscode", "queries", "highlights.scm"), + path.join( + repoRoot, + "extensions", + "zed", + "languages", + "silverscript", + "highlights.scm", + ), + path.join( + repoRoot, + "extensions", + "silverscript.nvim", + "queries", + "silverscript", + "highlights.scm", + ), +]; + +async function main() { + for (const target of targets) { + await mkdir(path.dirname(target), { recursive: true }); + await copyFile(source, target); + const relativeTarget = path.relative(repoRoot, target); + console.log(`synced ${relativeTarget}`); + } +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/tree-sitter/scripts/sync-vscode-wasm.mjs b/tree-sitter/scripts/sync-vscode-wasm.mjs new file mode 100644 index 00000000..85bed391 --- /dev/null +++ b/tree-sitter/scripts/sync-vscode-wasm.mjs @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +import { copyFile, mkdir } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); +const treeSitterDir = path.resolve(scriptDir, ".."); +const repoRoot = path.resolve(treeSitterDir, ".."); + +const source = path.join(treeSitterDir, "tree-sitter-silverscript.wasm"); +const target = path.join( + repoRoot, + "extensions", + "vscode", + "assets", + "tree-sitter-silverscript.wasm", +); + +async function main() { + await mkdir(path.dirname(target), { recursive: true }); + await copyFile(source, target); + const relativeTarget = path.relative(repoRoot, target); + console.log(`synced ${relativeTarget}`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/tree-sitter/scripts/sync-zed-wasm.mjs b/tree-sitter/scripts/sync-zed-wasm.mjs new file mode 100644 index 00000000..26000bc8 --- /dev/null +++ b/tree-sitter/scripts/sync-zed-wasm.mjs @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +import { copyFile, mkdir } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); +const treeSitterDir = path.resolve(scriptDir, ".."); +const repoRoot = path.resolve(treeSitterDir, ".."); + +const source = path.join(treeSitterDir, "tree-sitter-silverscript.wasm"); +const target = path.join( + repoRoot, + "extensions", + "zed", + "grammars", + "silverscript.wasm", +); + +async function main() { + await mkdir(path.dirname(target), { recursive: true }); + await copyFile(source, target); + const relativeTarget = path.relative(repoRoot, target); + console.log(`synced ${relativeTarget}`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/tree-sitter/setup.py b/tree-sitter/setup.py new file mode 100644 index 00000000..8fa1d900 --- /dev/null +++ b/tree-sitter/setup.py @@ -0,0 +1,77 @@ +from os import path +from sysconfig import get_config_var + +from setuptools import Extension, find_packages, setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.egg_info import egg_info +from wheel.bdist_wheel import bdist_wheel + + +class Build(build): + def run(self): + if path.isdir("queries"): + dest = path.join(self.build_lib, "tree_sitter_silverscript", "queries") + self.copy_tree("queries", dest) + super().run() + + +class BuildExt(build_ext): + def build_extension(self, ext: Extension): + if self.compiler.compiler_type != "msvc": + ext.extra_compile_args = ["-std=c11", "-fvisibility=hidden"] + else: + ext.extra_compile_args = ["/std:c11", "/utf-8"] + if path.exists("src/scanner.c"): + ext.sources.append("src/scanner.c") + if ext.py_limited_api: + ext.define_macros.append(("Py_LIMITED_API", "0x030A0000")) + super().build_extension(ext) + + +class BdistWheel(bdist_wheel): + def get_tag(self): + python, abi, platform = super().get_tag() + if python.startswith("cp") and not get_config_var("Py_GIL_DISABLED"): + python, abi = "cp310", "abi3" + return python, abi, platform + + +class EggInfo(egg_info): + def find_sources(self): + super().find_sources() + self.filelist.recursive_include("queries", "*.scm") + self.filelist.include("src/tree_sitter/*.h") + + +setup( + packages=find_packages("bindings/python"), + package_dir={"": "bindings/python"}, + package_data={ + "tree_sitter_silverscript": ["*.pyi", "py.typed"], + "tree_sitter_silverscript.queries": ["*.scm"], + }, + ext_package="tree_sitter_silverscript", + ext_modules=[ + Extension( + name="_binding", + sources=[ + "bindings/python/tree_sitter_silverscript/binding.c", + "src/parser.c", + ], + define_macros=[ + ("PY_SSIZE_T_CLEAN", None), + ("TREE_SITTER_HIDE_SYMBOLS", None), + ], + include_dirs=["src"], + py_limited_api=not get_config_var("Py_GIL_DISABLED"), + ) + ], + cmdclass={ + "build": Build, + "build_ext": BuildExt, + "bdist_wheel": BdistWheel, + "egg_info": EggInfo, + }, + zip_safe=False +) diff --git a/tree-sitter/src/grammar.json b/tree-sitter/src/grammar.json new file mode 100644 index 00000000..decc47b6 --- /dev/null +++ b/tree-sitter/src/grammar.json @@ -0,0 +1,2469 @@ +{ + "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", + "name": "silverscript", + "word": "identifier", + "rules": { + "source_file": { + "type": "SEQ", + "members": [ + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "pragma_directive" + } + }, + { + "type": "SYMBOL", + "name": "contract_definition" + } + ] + }, + "pragma_directive": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "pragma" + }, + { + "type": "STRING", + "value": "silverscript" + }, + { + "type": "SYMBOL", + "name": "pragma_value" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "pragma_value": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "version_constraint" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "version_constraint" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + "version_constraint": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "version_operator" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "SYMBOL", + "name": "version_literal" + } + ] + }, + "version_operator": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "^" + }, + { + "type": "STRING", + "value": "~" + }, + { + "type": "STRING", + "value": ">=" + }, + { + "type": "STRING", + "value": ">" + }, + { + "type": "STRING", + "value": "<=" + }, + { + "type": "STRING", + "value": "<" + }, + { + "type": "STRING", + "value": "=" + } + ] + }, + "version_literal": { + "type": "TOKEN", + "content": { + "type": "PATTERN", + "value": "\\d+\\.\\d+\\.\\d+" + } + }, + "contract_definition": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "contract" + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "SYMBOL", + "name": "parameter_list" + }, + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "contract_item" + } + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "contract_item": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "constant_definition" + }, + { + "type": "SYMBOL", + "name": "contract_field_definition" + }, + { + "type": "SYMBOL", + "name": "function_definition" + } + ] + }, + "function_definition": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "entrypoint" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "function" + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "SYMBOL", + "name": "parameter_list" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "return_type_list" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "statement" + } + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "constant_definition": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "STRING", + "value": "constant" + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "STRING", + "value": "=" + }, + { + "type": "FIELD", + "name": "value", + "content": { + "type": "SYMBOL", + "name": "expression" + } + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "contract_field_definition": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "STRING", + "value": "=" + }, + { + "type": "FIELD", + "name": "value", + "content": { + "type": "SYMBOL", + "name": "expression" + } + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "parameter_list": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "(" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "parameter" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "parameter" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "parameter": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "SYMBOL", + "name": "identifier" + } + ] + }, + "return_type_list": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": ":" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "type_name" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "block": { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "statement" + } + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + { + "type": "SYMBOL", + "name": "statement" + } + ] + }, + "statement": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "variable_definition" + }, + { + "type": "SYMBOL", + "name": "tuple_assignment" + }, + { + "type": "SYMBOL", + "name": "push_statement" + }, + { + "type": "SYMBOL", + "name": "state_function_call_assignment" + }, + { + "type": "SYMBOL", + "name": "function_call_assignment" + }, + { + "type": "SYMBOL", + "name": "call_statement" + }, + { + "type": "SYMBOL", + "name": "return_statement" + }, + { + "type": "SYMBOL", + "name": "assign_statement" + }, + { + "type": "SYMBOL", + "name": "time_op_statement" + }, + { + "type": "SYMBOL", + "name": "require_statement" + }, + { + "type": "SYMBOL", + "name": "if_statement" + }, + { + "type": "SYMBOL", + "name": "for_statement" + }, + { + "type": "SYMBOL", + "name": "yield_statement" + }, + { + "type": "SYMBOL", + "name": "console_statement" + } + ] + }, + "variable_definition": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "modifier" + } + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "=" + }, + { + "type": "FIELD", + "name": "value", + "content": { + "type": "SYMBOL", + "name": "expression" + } + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "tuple_assignment": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "STRING", + "value": "=" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "push_statement": { + "type": "SEQ", + "members": [ + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "STRING", + "value": ".push" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "function_call_assignment": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "(" + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "typed_binding" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "typed_binding" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "STRING", + "value": ")" + }, + { + "type": "STRING", + "value": "=" + }, + { + "type": "SYMBOL", + "name": "function_call" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "state_function_call_assignment": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "state_typed_binding" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "state_typed_binding" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "STRING", + "value": "}" + }, + { + "type": "STRING", + "value": "=" + }, + { + "type": "SYMBOL", + "name": "function_call" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "typed_binding": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "SYMBOL", + "name": "identifier" + } + ] + }, + "state_typed_binding": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "STRING", + "value": ":" + }, + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "SYMBOL", + "name": "identifier" + } + ] + }, + "call_statement": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "function_call" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "return_statement": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "return" + }, + { + "type": "SYMBOL", + "name": "expression_list" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "assign_statement": { + "type": "SEQ", + "members": [ + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "identifier" + } + }, + { + "type": "STRING", + "value": "=" + }, + { + "type": "FIELD", + "name": "value", + "content": { + "type": "SYMBOL", + "name": "expression" + } + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "time_op_statement": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "require" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "tx_var" + }, + { + "type": "STRING", + "value": ">=" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "require_message" + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "require_statement": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "require" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "require_message" + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "require_message": { + "type": "SYMBOL", + "name": "string_literal" + }, + "if_statement": { + "type": "PREC_RIGHT", + "value": 0, + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "if" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + }, + { + "type": "SYMBOL", + "name": "block" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "else" + }, + { + "type": "SYMBOL", + "name": "block" + } + ] + }, + { + "type": "BLANK" + } + ] + } + ] + } + }, + "for_statement": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "for" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + }, + { + "type": "SYMBOL", + "name": "block" + } + ] + }, + "yield_statement": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "yield" + }, + { + "type": "SYMBOL", + "name": "expression_list" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "console_statement": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "console.log" + }, + { + "type": "SYMBOL", + "name": "console_parameter_list" + }, + { + "type": "STRING", + "value": ";" + } + ] + }, + "console_parameter_list": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "(" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "console_parameter" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "console_parameter" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "console_parameter": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "SYMBOL", + "name": "literal" + } + ] + }, + "expression": { + "type": "SYMBOL", + "name": "logical_or" + }, + "logical_or": { + "type": "PREC_LEFT", + "value": 1, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "logical_and" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "||" + }, + { + "type": "SYMBOL", + "name": "logical_and" + } + ] + } + } + ] + } + }, + "logical_and": { + "type": "PREC_LEFT", + "value": 2, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "bit_or" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "&&" + }, + { + "type": "SYMBOL", + "name": "bit_or" + } + ] + } + } + ] + } + }, + "bit_or": { + "type": "PREC_LEFT", + "value": 3, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "bit_xor" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "|" + }, + { + "type": "SYMBOL", + "name": "bit_xor" + } + ] + } + } + ] + } + }, + "bit_xor": { + "type": "PREC_LEFT", + "value": 4, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "bit_and" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "^" + }, + { + "type": "SYMBOL", + "name": "bit_and" + } + ] + } + } + ] + } + }, + "bit_and": { + "type": "PREC_LEFT", + "value": 5, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "equality" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "&" + }, + { + "type": "SYMBOL", + "name": "equality" + } + ] + } + } + ] + } + }, + "equality": { + "type": "PREC_LEFT", + "value": 6, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "comparison" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "==" + }, + { + "type": "STRING", + "value": "!=" + } + ] + }, + { + "type": "SYMBOL", + "name": "comparison" + } + ] + } + } + ] + } + }, + "comparison": { + "type": "PREC_LEFT", + "value": 7, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "term" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "<=" + }, + { + "type": "STRING", + "value": "<" + }, + { + "type": "STRING", + "value": ">=" + }, + { + "type": "STRING", + "value": ">" + } + ] + }, + { + "type": "SYMBOL", + "name": "term" + } + ] + } + } + ] + } + }, + "term": { + "type": "PREC_LEFT", + "value": 8, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "factor" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "+" + }, + { + "type": "STRING", + "value": "-" + } + ] + }, + { + "type": "SYMBOL", + "name": "factor" + } + ] + } + } + ] + } + }, + "factor": { + "type": "PREC_LEFT", + "value": 9, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "unary" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "*" + }, + { + "type": "STRING", + "value": "/" + }, + { + "type": "STRING", + "value": "%" + } + ] + }, + { + "type": "SYMBOL", + "name": "unary" + } + ] + } + } + ] + } + }, + "unary": { + "type": "PREC_RIGHT", + "value": 10, + "content": { + "type": "SEQ", + "members": [ + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "unary_op" + } + }, + { + "type": "SYMBOL", + "name": "postfix" + } + ] + } + }, + "unary_op": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "!" + }, + { + "type": "STRING", + "value": "-" + } + ] + }, + "postfix": { + "type": "PREC_LEFT", + "value": 11, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "primary" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "postfix_op" + } + } + ] + } + }, + "postfix_op": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "tuple_index" + }, + { + "type": "SYMBOL", + "name": "unary_suffix" + }, + { + "type": "SYMBOL", + "name": "split_call" + }, + { + "type": "SYMBOL", + "name": "slice_call" + }, + { + "type": "SYMBOL", + "name": "reverse_call" + } + ] + }, + "tuple_index": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "[" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": "]" + } + ] + }, + "unary_suffix": { + "type": "STRING", + "value": ".length" + }, + "split_call": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": ".split" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "slice_call": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": ".slice" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "reverse_call": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": ".reverse" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "primary": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "parenthesized" + }, + { + "type": "SYMBOL", + "name": "cast" + }, + { + "type": "SYMBOL", + "name": "function_call" + }, + { + "type": "SYMBOL", + "name": "instantiation" + }, + { + "type": "SYMBOL", + "name": "state_object" + }, + { + "type": "SYMBOL", + "name": "introspection" + }, + { + "type": "SYMBOL", + "name": "array" + }, + { + "type": "SYMBOL", + "name": "nullary_op" + }, + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "SYMBOL", + "name": "literal" + } + ] + }, + "parenthesized": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "cast": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "type_name" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "expression" + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "function_call": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "SYMBOL", + "name": "expression_list" + } + ] + }, + "expression_list": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "(" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "expression" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "instantiation": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "new" + }, + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "SYMBOL", + "name": "expression_list" + } + ] + }, + "state_object": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "state_entry" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "state_entry" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "state_entry": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "STRING", + "value": ":" + }, + { + "type": "SYMBOL", + "name": "expression" + } + ] + }, + "introspection": { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "FIELD", + "name": "root", + "content": { + "type": "SYMBOL", + "name": "output_root" + } + }, + { + "type": "FIELD", + "name": "index", + "content": { + "type": "SYMBOL", + "name": "tuple_index" + } + }, + { + "type": "FIELD", + "name": "field", + "content": { + "type": "SYMBOL", + "name": "output_field" + } + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "FIELD", + "name": "root", + "content": { + "type": "SYMBOL", + "name": "input_root" + } + }, + { + "type": "FIELD", + "name": "index", + "content": { + "type": "SYMBOL", + "name": "tuple_index" + } + }, + { + "type": "FIELD", + "name": "field", + "content": { + "type": "SYMBOL", + "name": "input_field" + } + } + ] + } + ] + }, + "output_root": { + "type": "STRING", + "value": "tx.outputs" + }, + "input_root": { + "type": "STRING", + "value": "tx.inputs" + }, + "output_field": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "." + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "output_field_name" + } + } + ] + }, + "output_field_name": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "value" + }, + { + "type": "STRING", + "value": "scriptPubKey" + } + ] + }, + "input_field": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "." + }, + { + "type": "FIELD", + "name": "name", + "content": { + "type": "SYMBOL", + "name": "input_field_name" + } + } + ] + }, + "input_field_name": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "value" + }, + { + "type": "STRING", + "value": "scriptPubKey" + }, + { + "type": "STRING", + "value": "outpointTransactionHash" + }, + { + "type": "STRING", + "value": "outpointIndex" + }, + { + "type": "STRING", + "value": "sigScript" + } + ] + }, + "array": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "[" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "expression" + }, + { + "type": "REPEAT", + "content": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "SYMBOL", + "name": "expression" + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "," + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "]" + } + ] + }, + "modifier": { + "type": "STRING", + "value": "constant" + }, + "type_name": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "base_type" + }, + { + "type": "REPEAT", + "content": { + "type": "SYMBOL", + "name": "array_suffix" + } + } + ] + }, + "base_type": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "int" + }, + { + "type": "STRING", + "value": "bool" + }, + { + "type": "STRING", + "value": "string" + }, + { + "type": "STRING", + "value": "pubkey" + }, + { + "type": "STRING", + "value": "sig" + }, + { + "type": "STRING", + "value": "datasig" + }, + { + "type": "STRING", + "value": "byte" + } + ] + }, + "array_suffix": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "[" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "array_size" + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "]" + } + ] + }, + "array_size": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "identifier" + }, + { + "type": "SYMBOL", + "name": "array_bound" + } + ] + }, + "array_bound": { + "type": "TOKEN", + "content": { + "type": "PATTERN", + "value": "[1-9][0-9]*" + } + }, + "literal": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "boolean_literal" + }, + { + "type": "SYMBOL", + "name": "number_literal" + }, + { + "type": "SYMBOL", + "name": "string_literal" + }, + { + "type": "SYMBOL", + "name": "date_literal" + }, + { + "type": "SYMBOL", + "name": "hex_literal" + } + ] + }, + "boolean_literal": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "true" + }, + { + "type": "STRING", + "value": "false" + } + ] + }, + "number_literal": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "number" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "number_unit" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + "number_unit": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "litras" + }, + { + "type": "STRING", + "value": "grains" + }, + { + "type": "STRING", + "value": "kas" + }, + { + "type": "STRING", + "value": "seconds" + }, + { + "type": "STRING", + "value": "minutes" + }, + { + "type": "STRING", + "value": "hours" + }, + { + "type": "STRING", + "value": "days" + }, + { + "type": "STRING", + "value": "weeks" + } + ] + }, + "number": { + "type": "TOKEN", + "content": { + "type": "PATTERN", + "value": "-?\\d+(?:_\\d+)*(?:[eE]\\d+(?:_\\d+)*)?" + } + }, + "string_literal": { + "type": "TOKEN", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "PATTERN", + "value": "\"([^\"\\\\\\n]|\\\\.)*\"" + }, + { + "type": "PATTERN", + "value": "'([^'\\\\\\n]|\\\\.)*'" + } + ] + } + }, + "date_literal": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "date" + }, + { + "type": "STRING", + "value": "(" + }, + { + "type": "SYMBOL", + "name": "string_literal" + }, + { + "type": "STRING", + "value": ")" + } + ] + }, + "hex_literal": { + "type": "TOKEN", + "content": { + "type": "PATTERN", + "value": "0[xX][0-9a-fA-F]*" + } + }, + "tx_var": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "this.age" + }, + { + "type": "STRING", + "value": "tx.time" + } + ] + }, + "nullary_op": { + "type": "CHOICE", + "members": [ + { + "type": "STRING", + "value": "this.activeInputIndex" + }, + { + "type": "STRING", + "value": "this.activeScriptPubKey" + }, + { + "type": "STRING", + "value": "this.scriptSizeDataPrefix" + }, + { + "type": "STRING", + "value": "this.scriptSize" + }, + { + "type": "STRING", + "value": "tx.inputs.length" + }, + { + "type": "STRING", + "value": "tx.outputs.length" + }, + { + "type": "STRING", + "value": "tx.version" + }, + { + "type": "STRING", + "value": "tx.locktime" + } + ] + }, + "identifier": { + "type": "TOKEN", + "content": { + "type": "PREC", + "value": -1, + "content": { + "type": "PATTERN", + "value": "[A-Za-z][A-Za-z0-9_]*" + } + } + }, + "comment": { + "type": "TOKEN", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "PATTERN", + "value": "\\/\\/[^\\n]*" + }, + { + "type": "PATTERN", + "value": "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/" + } + ] + } + } + }, + "extras": [ + { + "type": "PATTERN", + "value": "\\s" + }, + { + "type": "SYMBOL", + "name": "comment" + } + ], + "conflicts": [], + "precedences": [], + "externals": [], + "inline": [], + "supertypes": [], + "reserved": {} +} \ No newline at end of file diff --git a/tree-sitter/src/node-types.json b/tree-sitter/src/node-types.json new file mode 100644 index 00000000..c948b7df --- /dev/null +++ b/tree-sitter/src/node-types.json @@ -0,0 +1,1806 @@ +[ + { + "type": "array", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "array_size", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "array_bound", + "named": true + }, + { + "type": "identifier", + "named": true + } + ] + } + }, + { + "type": "array_suffix", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": false, + "types": [ + { + "type": "array_size", + "named": true + } + ] + } + }, + { + "type": "assign_statement", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + }, + "value": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + } + }, + { + "type": "base_type", + "named": true, + "fields": {} + }, + { + "type": "bit_and", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "equality", + "named": true + } + ] + } + }, + { + "type": "bit_or", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "bit_xor", + "named": true + } + ] + } + }, + { + "type": "bit_xor", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "bit_and", + "named": true + } + ] + } + }, + { + "type": "block", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "statement", + "named": true + } + ] + } + }, + { + "type": "boolean_literal", + "named": true, + "fields": {} + }, + { + "type": "call_statement", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "function_call", + "named": true + } + ] + } + }, + { + "type": "cast", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression", + "named": true + }, + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "comparison", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "term", + "named": true + } + ] + } + }, + { + "type": "console_parameter", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + }, + { + "type": "literal", + "named": true + } + ] + } + }, + { + "type": "console_parameter_list", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "console_parameter", + "named": true + } + ] + } + }, + { + "type": "console_statement", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "console_parameter_list", + "named": true + } + ] + } + }, + { + "type": "constant_definition", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + }, + "value": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "contract_definition", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + } + }, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "contract_item", + "named": true + }, + { + "type": "parameter_list", + "named": true + } + ] + } + }, + { + "type": "contract_field_definition", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + }, + "value": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "contract_item", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "constant_definition", + "named": true + }, + { + "type": "contract_field_definition", + "named": true + }, + { + "type": "function_definition", + "named": true + } + ] + } + }, + { + "type": "date_literal", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "string_literal", + "named": true + } + ] + } + }, + { + "type": "equality", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "comparison", + "named": true + } + ] + } + }, + { + "type": "expression", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "logical_or", + "named": true + } + ] + } + }, + { + "type": "expression_list", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "factor", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "unary", + "named": true + } + ] + } + }, + { + "type": "for_statement", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "block", + "named": true + }, + { + "type": "expression", + "named": true + }, + { + "type": "identifier", + "named": true + } + ] + } + }, + { + "type": "function_call", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression_list", + "named": true + }, + { + "type": "identifier", + "named": true + } + ] + } + }, + { + "type": "function_call_assignment", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "function_call", + "named": true + }, + { + "type": "typed_binding", + "named": true + } + ] + } + }, + { + "type": "function_definition", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + } + }, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "parameter_list", + "named": true + }, + { + "type": "return_type_list", + "named": true + }, + { + "type": "statement", + "named": true + } + ] + } + }, + { + "type": "if_statement", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "block", + "named": true + }, + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "input_field", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "input_field_name", + "named": true + } + ] + } + } + }, + { + "type": "input_field_name", + "named": true, + "fields": {} + }, + { + "type": "instantiation", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression_list", + "named": true + }, + { + "type": "identifier", + "named": true + } + ] + } + }, + { + "type": "introspection", + "named": true, + "fields": { + "field": { + "multiple": false, + "required": true, + "types": [ + { + "type": "input_field", + "named": true + }, + { + "type": "output_field", + "named": true + } + ] + }, + "index": { + "multiple": false, + "required": true, + "types": [ + { + "type": "tuple_index", + "named": true + } + ] + }, + "root": { + "multiple": false, + "required": true, + "types": [ + { + "type": "input_root", + "named": true + }, + { + "type": "output_root", + "named": true + } + ] + } + } + }, + { + "type": "literal", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "boolean_literal", + "named": true + }, + { + "type": "date_literal", + "named": true + }, + { + "type": "hex_literal", + "named": true + }, + { + "type": "number_literal", + "named": true + }, + { + "type": "string_literal", + "named": true + } + ] + } + }, + { + "type": "logical_and", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "bit_or", + "named": true + } + ] + } + }, + { + "type": "logical_or", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "logical_and", + "named": true + } + ] + } + }, + { + "type": "modifier", + "named": true, + "fields": {} + }, + { + "type": "nullary_op", + "named": true, + "fields": {} + }, + { + "type": "number_literal", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "number", + "named": true + }, + { + "type": "number_unit", + "named": true + } + ] + } + }, + { + "type": "number_unit", + "named": true, + "fields": {} + }, + { + "type": "output_field", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "output_field_name", + "named": true + } + ] + } + } + }, + { + "type": "output_field_name", + "named": true, + "fields": {} + }, + { + "type": "parameter", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + }, + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "parameter_list", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "parameter", + "named": true + } + ] + } + }, + { + "type": "parenthesized", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "postfix", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "postfix_op", + "named": true + }, + { + "type": "primary", + "named": true + } + ] + } + }, + { + "type": "postfix_op", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "reverse_call", + "named": true + }, + { + "type": "slice_call", + "named": true + }, + { + "type": "split_call", + "named": true + }, + { + "type": "tuple_index", + "named": true + }, + { + "type": "unary_suffix", + "named": true + } + ] + } + }, + { + "type": "pragma_directive", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "pragma_value", + "named": true + } + ] + } + }, + { + "type": "pragma_value", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "version_constraint", + "named": true + } + ] + } + }, + { + "type": "primary", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "array", + "named": true + }, + { + "type": "cast", + "named": true + }, + { + "type": "function_call", + "named": true + }, + { + "type": "identifier", + "named": true + }, + { + "type": "instantiation", + "named": true + }, + { + "type": "introspection", + "named": true + }, + { + "type": "literal", + "named": true + }, + { + "type": "nullary_op", + "named": true + }, + { + "type": "parenthesized", + "named": true + }, + { + "type": "state_object", + "named": true + } + ] + } + }, + { + "type": "push_statement", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + } + }, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "require_message", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "string_literal", + "named": true + } + ] + } + }, + { + "type": "require_statement", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression", + "named": true + }, + { + "type": "require_message", + "named": true + } + ] + } + }, + { + "type": "return_statement", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression_list", + "named": true + } + ] + } + }, + { + "type": "return_type_list", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "reverse_call", + "named": true, + "fields": {} + }, + { + "type": "slice_call", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "source_file", + "named": true, + "root": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "contract_definition", + "named": true + }, + { + "type": "pragma_directive", + "named": true + } + ] + } + }, + { + "type": "split_call", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "state_entry", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression", + "named": true + }, + { + "type": "identifier", + "named": true + } + ] + } + }, + { + "type": "state_function_call_assignment", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "function_call", + "named": true + }, + { + "type": "state_typed_binding", + "named": true + } + ] + } + }, + { + "type": "state_object", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "state_entry", + "named": true + } + ] + } + }, + { + "type": "state_typed_binding", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + }, + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "statement", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "assign_statement", + "named": true + }, + { + "type": "call_statement", + "named": true + }, + { + "type": "console_statement", + "named": true + }, + { + "type": "for_statement", + "named": true + }, + { + "type": "function_call_assignment", + "named": true + }, + { + "type": "if_statement", + "named": true + }, + { + "type": "push_statement", + "named": true + }, + { + "type": "require_statement", + "named": true + }, + { + "type": "return_statement", + "named": true + }, + { + "type": "state_function_call_assignment", + "named": true + }, + { + "type": "time_op_statement", + "named": true + }, + { + "type": "tuple_assignment", + "named": true + }, + { + "type": "variable_definition", + "named": true + }, + { + "type": "yield_statement", + "named": true + } + ] + } + }, + { + "type": "term", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "factor", + "named": true + } + ] + } + }, + { + "type": "time_op_statement", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression", + "named": true + }, + { + "type": "require_message", + "named": true + }, + { + "type": "tx_var", + "named": true + } + ] + } + }, + { + "type": "tuple_assignment", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "expression", + "named": true + }, + { + "type": "identifier", + "named": true + }, + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "tuple_index", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + { + "type": "tx_var", + "named": true, + "fields": {} + }, + { + "type": "type_name", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "array_suffix", + "named": true + }, + { + "type": "base_type", + "named": true + } + ] + } + }, + { + "type": "typed_binding", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + }, + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "unary", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "postfix", + "named": true + }, + { + "type": "unary_op", + "named": true + } + ] + } + }, + { + "type": "unary_op", + "named": true, + "fields": {} + }, + { + "type": "variable_definition", + "named": true, + "fields": { + "name": { + "multiple": false, + "required": true, + "types": [ + { + "type": "identifier", + "named": true + } + ] + }, + "value": { + "multiple": false, + "required": false, + "types": [ + { + "type": "expression", + "named": true + } + ] + } + }, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "modifier", + "named": true + }, + { + "type": "type_name", + "named": true + } + ] + } + }, + { + "type": "version_constraint", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "version_literal", + "named": true + }, + { + "type": "version_operator", + "named": true + } + ] + } + }, + { + "type": "version_operator", + "named": true, + "fields": {} + }, + { + "type": "yield_statement", + "named": true, + "fields": {}, + "children": { + "multiple": false, + "required": true, + "types": [ + { + "type": "expression_list", + "named": true + } + ] + } + }, + { + "type": "!", + "named": false + }, + { + "type": "!=", + "named": false + }, + { + "type": "%", + "named": false + }, + { + "type": "&", + "named": false + }, + { + "type": "&&", + "named": false + }, + { + "type": "(", + "named": false + }, + { + "type": ")", + "named": false + }, + { + "type": "*", + "named": false + }, + { + "type": "+", + "named": false + }, + { + "type": ",", + "named": false + }, + { + "type": "-", + "named": false + }, + { + "type": ".", + "named": false + }, + { + "type": ".push", + "named": false + }, + { + "type": ".reverse", + "named": false + }, + { + "type": ".slice", + "named": false + }, + { + "type": ".split", + "named": false + }, + { + "type": "/", + "named": false + }, + { + "type": ":", + "named": false + }, + { + "type": ";", + "named": false + }, + { + "type": "<", + "named": false + }, + { + "type": "<=", + "named": false + }, + { + "type": "=", + "named": false + }, + { + "type": "==", + "named": false + }, + { + "type": ">", + "named": false + }, + { + "type": ">=", + "named": false + }, + { + "type": "[", + "named": false + }, + { + "type": "]", + "named": false + }, + { + "type": "^", + "named": false + }, + { + "type": "array_bound", + "named": true + }, + { + "type": "bool", + "named": false + }, + { + "type": "byte", + "named": false + }, + { + "type": "comment", + "named": true, + "extra": true + }, + { + "type": "console.log", + "named": false + }, + { + "type": "constant", + "named": false + }, + { + "type": "contract", + "named": false + }, + { + "type": "datasig", + "named": false + }, + { + "type": "date", + "named": false + }, + { + "type": "days", + "named": false + }, + { + "type": "else", + "named": false + }, + { + "type": "entrypoint", + "named": false + }, + { + "type": "false", + "named": false + }, + { + "type": "for", + "named": false + }, + { + "type": "function", + "named": false + }, + { + "type": "grains", + "named": false + }, + { + "type": "hex_literal", + "named": true + }, + { + "type": "hours", + "named": false + }, + { + "type": "identifier", + "named": true + }, + { + "type": "if", + "named": false + }, + { + "type": "input_root", + "named": true + }, + { + "type": "int", + "named": false + }, + { + "type": "kas", + "named": false + }, + { + "type": "litras", + "named": false + }, + { + "type": "minutes", + "named": false + }, + { + "type": "new", + "named": false + }, + { + "type": "number", + "named": true + }, + { + "type": "outpointIndex", + "named": false + }, + { + "type": "outpointTransactionHash", + "named": false + }, + { + "type": "output_root", + "named": true + }, + { + "type": "pragma", + "named": false + }, + { + "type": "pubkey", + "named": false + }, + { + "type": "require", + "named": false + }, + { + "type": "return", + "named": false + }, + { + "type": "scriptPubKey", + "named": false + }, + { + "type": "seconds", + "named": false + }, + { + "type": "sig", + "named": false + }, + { + "type": "sigScript", + "named": false + }, + { + "type": "silverscript", + "named": false + }, + { + "type": "string", + "named": false + }, + { + "type": "string_literal", + "named": true + }, + { + "type": "this.activeInputIndex", + "named": false + }, + { + "type": "this.activeScriptPubKey", + "named": false + }, + { + "type": "this.age", + "named": false + }, + { + "type": "this.scriptSize", + "named": false + }, + { + "type": "this.scriptSizeDataPrefix", + "named": false + }, + { + "type": "true", + "named": false + }, + { + "type": "tx.inputs.length", + "named": false + }, + { + "type": "tx.locktime", + "named": false + }, + { + "type": "tx.outputs.length", + "named": false + }, + { + "type": "tx.time", + "named": false + }, + { + "type": "tx.version", + "named": false + }, + { + "type": "unary_suffix", + "named": true + }, + { + "type": "value", + "named": false + }, + { + "type": "version_literal", + "named": true + }, + { + "type": "weeks", + "named": false + }, + { + "type": "yield", + "named": false + }, + { + "type": "{", + "named": false + }, + { + "type": "|", + "named": false + }, + { + "type": "||", + "named": false + }, + { + "type": "}", + "named": false + }, + { + "type": "~", + "named": false + } +] \ No newline at end of file diff --git a/tree-sitter/src/parser.c b/tree-sitter/src/parser.c new file mode 100644 index 00000000..6202cff1 --- /dev/null +++ b/tree-sitter/src/parser.c @@ -0,0 +1,13869 @@ +/* Automatically @generated by tree-sitter */ + +#include "tree_sitter/parser.h" + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +#define LANGUAGE_VERSION 15 +#define STATE_COUNT 389 +#define LARGE_STATE_COUNT 2 +#define SYMBOL_COUNT 192 +#define ALIAS_COUNT 0 +#define TOKEN_COUNT 91 +#define EXTERNAL_TOKEN_COUNT 0 +#define FIELD_COUNT 5 +#define MAX_ALIAS_SEQUENCE_LENGTH 9 +#define MAX_RESERVED_WORD_SET_SIZE 0 +#define PRODUCTION_ID_COUNT 8 +#define SUPERTYPE_COUNT 0 + +enum ts_symbol_identifiers { + sym_identifier = 1, + anon_sym_pragma = 2, + anon_sym_silverscript = 3, + anon_sym_SEMI = 4, + anon_sym_CARET = 5, + anon_sym_TILDE = 6, + anon_sym_GT_EQ = 7, + anon_sym_GT = 8, + anon_sym_LT_EQ = 9, + anon_sym_LT = 10, + anon_sym_EQ = 11, + sym_version_literal = 12, + anon_sym_contract = 13, + anon_sym_LBRACE = 14, + anon_sym_RBRACE = 15, + anon_sym_entrypoint = 16, + anon_sym_function = 17, + anon_sym_constant = 18, + anon_sym_LPAREN = 19, + anon_sym_COMMA = 20, + anon_sym_RPAREN = 21, + anon_sym_COLON = 22, + anon_sym_DOTpush = 23, + anon_sym_return = 24, + anon_sym_require = 25, + anon_sym_if = 26, + anon_sym_else = 27, + anon_sym_for = 28, + anon_sym_yield = 29, + anon_sym_console_DOTlog = 30, + anon_sym_PIPE_PIPE = 31, + anon_sym_AMP_AMP = 32, + anon_sym_PIPE = 33, + anon_sym_AMP = 34, + anon_sym_EQ_EQ = 35, + anon_sym_BANG_EQ = 36, + anon_sym_PLUS = 37, + anon_sym_DASH = 38, + anon_sym_STAR = 39, + anon_sym_SLASH = 40, + anon_sym_PERCENT = 41, + anon_sym_BANG = 42, + anon_sym_LBRACK = 43, + anon_sym_RBRACK = 44, + sym_unary_suffix = 45, + anon_sym_DOTsplit = 46, + anon_sym_DOTslice = 47, + anon_sym_DOTreverse = 48, + anon_sym_new = 49, + sym_output_root = 50, + sym_input_root = 51, + anon_sym_DOT = 52, + anon_sym_value = 53, + anon_sym_scriptPubKey = 54, + anon_sym_outpointTransactionHash = 55, + anon_sym_outpointIndex = 56, + anon_sym_sigScript = 57, + anon_sym_int = 58, + anon_sym_bool = 59, + anon_sym_string = 60, + anon_sym_pubkey = 61, + anon_sym_sig = 62, + anon_sym_datasig = 63, + anon_sym_byte = 64, + sym_array_bound = 65, + anon_sym_true = 66, + anon_sym_false = 67, + anon_sym_litras = 68, + anon_sym_grains = 69, + anon_sym_kas = 70, + anon_sym_seconds = 71, + anon_sym_minutes = 72, + anon_sym_hours = 73, + anon_sym_days = 74, + anon_sym_weeks = 75, + sym_number = 76, + sym_string_literal = 77, + anon_sym_date = 78, + sym_hex_literal = 79, + anon_sym_this_DOTage = 80, + anon_sym_tx_DOTtime = 81, + anon_sym_this_DOTactiveInputIndex = 82, + anon_sym_this_DOTactiveScriptPubKey = 83, + anon_sym_this_DOTscriptSizeDataPrefix = 84, + anon_sym_this_DOTscriptSize = 85, + anon_sym_tx_DOTinputs_DOTlength = 86, + anon_sym_tx_DOToutputs_DOTlength = 87, + anon_sym_tx_DOTversion = 88, + anon_sym_tx_DOTlocktime = 89, + sym_comment = 90, + sym_source_file = 91, + sym_pragma_directive = 92, + sym_pragma_value = 93, + sym_version_constraint = 94, + sym_version_operator = 95, + sym_contract_definition = 96, + sym_contract_item = 97, + sym_function_definition = 98, + sym_constant_definition = 99, + sym_contract_field_definition = 100, + sym_parameter_list = 101, + sym_parameter = 102, + sym_return_type_list = 103, + sym_block = 104, + sym_statement = 105, + sym_variable_definition = 106, + sym_tuple_assignment = 107, + sym_push_statement = 108, + sym_function_call_assignment = 109, + sym_state_function_call_assignment = 110, + sym_typed_binding = 111, + sym_state_typed_binding = 112, + sym_call_statement = 113, + sym_return_statement = 114, + sym_assign_statement = 115, + sym_time_op_statement = 116, + sym_require_statement = 117, + sym_require_message = 118, + sym_if_statement = 119, + sym_for_statement = 120, + sym_yield_statement = 121, + sym_console_statement = 122, + sym_console_parameter_list = 123, + sym_console_parameter = 124, + sym_expression = 125, + sym_logical_or = 126, + sym_logical_and = 127, + sym_bit_or = 128, + sym_bit_xor = 129, + sym_bit_and = 130, + sym_equality = 131, + sym_comparison = 132, + sym_term = 133, + sym_factor = 134, + sym_unary = 135, + sym_unary_op = 136, + sym_postfix = 137, + sym_postfix_op = 138, + sym_tuple_index = 139, + sym_split_call = 140, + sym_slice_call = 141, + sym_reverse_call = 142, + sym_primary = 143, + sym_parenthesized = 144, + sym_cast = 145, + sym_function_call = 146, + sym_expression_list = 147, + sym_instantiation = 148, + sym_state_object = 149, + sym_state_entry = 150, + sym_introspection = 151, + sym_output_field = 152, + sym_output_field_name = 153, + sym_input_field = 154, + sym_input_field_name = 155, + sym_array = 156, + sym_modifier = 157, + sym_type_name = 158, + sym_base_type = 159, + sym_array_suffix = 160, + sym_array_size = 161, + sym_literal = 162, + sym_boolean_literal = 163, + sym_number_literal = 164, + sym_number_unit = 165, + sym_date_literal = 166, + sym_tx_var = 167, + sym_nullary_op = 168, + aux_sym_source_file_repeat1 = 169, + aux_sym_contract_definition_repeat1 = 170, + aux_sym_function_definition_repeat1 = 171, + aux_sym_parameter_list_repeat1 = 172, + aux_sym_return_type_list_repeat1 = 173, + aux_sym_variable_definition_repeat1 = 174, + aux_sym_function_call_assignment_repeat1 = 175, + aux_sym_state_function_call_assignment_repeat1 = 176, + aux_sym_console_parameter_list_repeat1 = 177, + aux_sym_logical_or_repeat1 = 178, + aux_sym_logical_and_repeat1 = 179, + aux_sym_bit_or_repeat1 = 180, + aux_sym_bit_xor_repeat1 = 181, + aux_sym_bit_and_repeat1 = 182, + aux_sym_equality_repeat1 = 183, + aux_sym_comparison_repeat1 = 184, + aux_sym_term_repeat1 = 185, + aux_sym_factor_repeat1 = 186, + aux_sym_unary_repeat1 = 187, + aux_sym_postfix_repeat1 = 188, + aux_sym_expression_list_repeat1 = 189, + aux_sym_state_object_repeat1 = 190, + aux_sym_type_name_repeat1 = 191, +}; + +static const char * const ts_symbol_names[] = { + [ts_builtin_sym_end] = "end", + [sym_identifier] = "identifier", + [anon_sym_pragma] = "pragma", + [anon_sym_silverscript] = "silverscript", + [anon_sym_SEMI] = ";", + [anon_sym_CARET] = "^", + [anon_sym_TILDE] = "~", + [anon_sym_GT_EQ] = ">=", + [anon_sym_GT] = ">", + [anon_sym_LT_EQ] = "<=", + [anon_sym_LT] = "<", + [anon_sym_EQ] = "=", + [sym_version_literal] = "version_literal", + [anon_sym_contract] = "contract", + [anon_sym_LBRACE] = "{", + [anon_sym_RBRACE] = "}", + [anon_sym_entrypoint] = "entrypoint", + [anon_sym_function] = "function", + [anon_sym_constant] = "constant", + [anon_sym_LPAREN] = "(", + [anon_sym_COMMA] = ",", + [anon_sym_RPAREN] = ")", + [anon_sym_COLON] = ":", + [anon_sym_DOTpush] = ".push", + [anon_sym_return] = "return", + [anon_sym_require] = "require", + [anon_sym_if] = "if", + [anon_sym_else] = "else", + [anon_sym_for] = "for", + [anon_sym_yield] = "yield", + [anon_sym_console_DOTlog] = "console.log", + [anon_sym_PIPE_PIPE] = "||", + [anon_sym_AMP_AMP] = "&&", + [anon_sym_PIPE] = "|", + [anon_sym_AMP] = "&", + [anon_sym_EQ_EQ] = "==", + [anon_sym_BANG_EQ] = "!=", + [anon_sym_PLUS] = "+", + [anon_sym_DASH] = "-", + [anon_sym_STAR] = "*", + [anon_sym_SLASH] = "/", + [anon_sym_PERCENT] = "%", + [anon_sym_BANG] = "!", + [anon_sym_LBRACK] = "[", + [anon_sym_RBRACK] = "]", + [sym_unary_suffix] = "unary_suffix", + [anon_sym_DOTsplit] = ".split", + [anon_sym_DOTslice] = ".slice", + [anon_sym_DOTreverse] = ".reverse", + [anon_sym_new] = "new", + [sym_output_root] = "output_root", + [sym_input_root] = "input_root", + [anon_sym_DOT] = ".", + [anon_sym_value] = "value", + [anon_sym_scriptPubKey] = "scriptPubKey", + [anon_sym_outpointTransactionHash] = "outpointTransactionHash", + [anon_sym_outpointIndex] = "outpointIndex", + [anon_sym_sigScript] = "sigScript", + [anon_sym_int] = "int", + [anon_sym_bool] = "bool", + [anon_sym_string] = "string", + [anon_sym_pubkey] = "pubkey", + [anon_sym_sig] = "sig", + [anon_sym_datasig] = "datasig", + [anon_sym_byte] = "byte", + [sym_array_bound] = "array_bound", + [anon_sym_true] = "true", + [anon_sym_false] = "false", + [anon_sym_litras] = "litras", + [anon_sym_grains] = "grains", + [anon_sym_kas] = "kas", + [anon_sym_seconds] = "seconds", + [anon_sym_minutes] = "minutes", + [anon_sym_hours] = "hours", + [anon_sym_days] = "days", + [anon_sym_weeks] = "weeks", + [sym_number] = "number", + [sym_string_literal] = "string_literal", + [anon_sym_date] = "date", + [sym_hex_literal] = "hex_literal", + [anon_sym_this_DOTage] = "this.age", + [anon_sym_tx_DOTtime] = "tx.time", + [anon_sym_this_DOTactiveInputIndex] = "this.activeInputIndex", + [anon_sym_this_DOTactiveScriptPubKey] = "this.activeScriptPubKey", + [anon_sym_this_DOTscriptSizeDataPrefix] = "this.scriptSizeDataPrefix", + [anon_sym_this_DOTscriptSize] = "this.scriptSize", + [anon_sym_tx_DOTinputs_DOTlength] = "tx.inputs.length", + [anon_sym_tx_DOToutputs_DOTlength] = "tx.outputs.length", + [anon_sym_tx_DOTversion] = "tx.version", + [anon_sym_tx_DOTlocktime] = "tx.locktime", + [sym_comment] = "comment", + [sym_source_file] = "source_file", + [sym_pragma_directive] = "pragma_directive", + [sym_pragma_value] = "pragma_value", + [sym_version_constraint] = "version_constraint", + [sym_version_operator] = "version_operator", + [sym_contract_definition] = "contract_definition", + [sym_contract_item] = "contract_item", + [sym_function_definition] = "function_definition", + [sym_constant_definition] = "constant_definition", + [sym_contract_field_definition] = "contract_field_definition", + [sym_parameter_list] = "parameter_list", + [sym_parameter] = "parameter", + [sym_return_type_list] = "return_type_list", + [sym_block] = "block", + [sym_statement] = "statement", + [sym_variable_definition] = "variable_definition", + [sym_tuple_assignment] = "tuple_assignment", + [sym_push_statement] = "push_statement", + [sym_function_call_assignment] = "function_call_assignment", + [sym_state_function_call_assignment] = "state_function_call_assignment", + [sym_typed_binding] = "typed_binding", + [sym_state_typed_binding] = "state_typed_binding", + [sym_call_statement] = "call_statement", + [sym_return_statement] = "return_statement", + [sym_assign_statement] = "assign_statement", + [sym_time_op_statement] = "time_op_statement", + [sym_require_statement] = "require_statement", + [sym_require_message] = "require_message", + [sym_if_statement] = "if_statement", + [sym_for_statement] = "for_statement", + [sym_yield_statement] = "yield_statement", + [sym_console_statement] = "console_statement", + [sym_console_parameter_list] = "console_parameter_list", + [sym_console_parameter] = "console_parameter", + [sym_expression] = "expression", + [sym_logical_or] = "logical_or", + [sym_logical_and] = "logical_and", + [sym_bit_or] = "bit_or", + [sym_bit_xor] = "bit_xor", + [sym_bit_and] = "bit_and", + [sym_equality] = "equality", + [sym_comparison] = "comparison", + [sym_term] = "term", + [sym_factor] = "factor", + [sym_unary] = "unary", + [sym_unary_op] = "unary_op", + [sym_postfix] = "postfix", + [sym_postfix_op] = "postfix_op", + [sym_tuple_index] = "tuple_index", + [sym_split_call] = "split_call", + [sym_slice_call] = "slice_call", + [sym_reverse_call] = "reverse_call", + [sym_primary] = "primary", + [sym_parenthesized] = "parenthesized", + [sym_cast] = "cast", + [sym_function_call] = "function_call", + [sym_expression_list] = "expression_list", + [sym_instantiation] = "instantiation", + [sym_state_object] = "state_object", + [sym_state_entry] = "state_entry", + [sym_introspection] = "introspection", + [sym_output_field] = "output_field", + [sym_output_field_name] = "output_field_name", + [sym_input_field] = "input_field", + [sym_input_field_name] = "input_field_name", + [sym_array] = "array", + [sym_modifier] = "modifier", + [sym_type_name] = "type_name", + [sym_base_type] = "base_type", + [sym_array_suffix] = "array_suffix", + [sym_array_size] = "array_size", + [sym_literal] = "literal", + [sym_boolean_literal] = "boolean_literal", + [sym_number_literal] = "number_literal", + [sym_number_unit] = "number_unit", + [sym_date_literal] = "date_literal", + [sym_tx_var] = "tx_var", + [sym_nullary_op] = "nullary_op", + [aux_sym_source_file_repeat1] = "source_file_repeat1", + [aux_sym_contract_definition_repeat1] = "contract_definition_repeat1", + [aux_sym_function_definition_repeat1] = "function_definition_repeat1", + [aux_sym_parameter_list_repeat1] = "parameter_list_repeat1", + [aux_sym_return_type_list_repeat1] = "return_type_list_repeat1", + [aux_sym_variable_definition_repeat1] = "variable_definition_repeat1", + [aux_sym_function_call_assignment_repeat1] = "function_call_assignment_repeat1", + [aux_sym_state_function_call_assignment_repeat1] = "state_function_call_assignment_repeat1", + [aux_sym_console_parameter_list_repeat1] = "console_parameter_list_repeat1", + [aux_sym_logical_or_repeat1] = "logical_or_repeat1", + [aux_sym_logical_and_repeat1] = "logical_and_repeat1", + [aux_sym_bit_or_repeat1] = "bit_or_repeat1", + [aux_sym_bit_xor_repeat1] = "bit_xor_repeat1", + [aux_sym_bit_and_repeat1] = "bit_and_repeat1", + [aux_sym_equality_repeat1] = "equality_repeat1", + [aux_sym_comparison_repeat1] = "comparison_repeat1", + [aux_sym_term_repeat1] = "term_repeat1", + [aux_sym_factor_repeat1] = "factor_repeat1", + [aux_sym_unary_repeat1] = "unary_repeat1", + [aux_sym_postfix_repeat1] = "postfix_repeat1", + [aux_sym_expression_list_repeat1] = "expression_list_repeat1", + [aux_sym_state_object_repeat1] = "state_object_repeat1", + [aux_sym_type_name_repeat1] = "type_name_repeat1", +}; + +static const TSSymbol ts_symbol_map[] = { + [ts_builtin_sym_end] = ts_builtin_sym_end, + [sym_identifier] = sym_identifier, + [anon_sym_pragma] = anon_sym_pragma, + [anon_sym_silverscript] = anon_sym_silverscript, + [anon_sym_SEMI] = anon_sym_SEMI, + [anon_sym_CARET] = anon_sym_CARET, + [anon_sym_TILDE] = anon_sym_TILDE, + [anon_sym_GT_EQ] = anon_sym_GT_EQ, + [anon_sym_GT] = anon_sym_GT, + [anon_sym_LT_EQ] = anon_sym_LT_EQ, + [anon_sym_LT] = anon_sym_LT, + [anon_sym_EQ] = anon_sym_EQ, + [sym_version_literal] = sym_version_literal, + [anon_sym_contract] = anon_sym_contract, + [anon_sym_LBRACE] = anon_sym_LBRACE, + [anon_sym_RBRACE] = anon_sym_RBRACE, + [anon_sym_entrypoint] = anon_sym_entrypoint, + [anon_sym_function] = anon_sym_function, + [anon_sym_constant] = anon_sym_constant, + [anon_sym_LPAREN] = anon_sym_LPAREN, + [anon_sym_COMMA] = anon_sym_COMMA, + [anon_sym_RPAREN] = anon_sym_RPAREN, + [anon_sym_COLON] = anon_sym_COLON, + [anon_sym_DOTpush] = anon_sym_DOTpush, + [anon_sym_return] = anon_sym_return, + [anon_sym_require] = anon_sym_require, + [anon_sym_if] = anon_sym_if, + [anon_sym_else] = anon_sym_else, + [anon_sym_for] = anon_sym_for, + [anon_sym_yield] = anon_sym_yield, + [anon_sym_console_DOTlog] = anon_sym_console_DOTlog, + [anon_sym_PIPE_PIPE] = anon_sym_PIPE_PIPE, + [anon_sym_AMP_AMP] = anon_sym_AMP_AMP, + [anon_sym_PIPE] = anon_sym_PIPE, + [anon_sym_AMP] = anon_sym_AMP, + [anon_sym_EQ_EQ] = anon_sym_EQ_EQ, + [anon_sym_BANG_EQ] = anon_sym_BANG_EQ, + [anon_sym_PLUS] = anon_sym_PLUS, + [anon_sym_DASH] = anon_sym_DASH, + [anon_sym_STAR] = anon_sym_STAR, + [anon_sym_SLASH] = anon_sym_SLASH, + [anon_sym_PERCENT] = anon_sym_PERCENT, + [anon_sym_BANG] = anon_sym_BANG, + [anon_sym_LBRACK] = anon_sym_LBRACK, + [anon_sym_RBRACK] = anon_sym_RBRACK, + [sym_unary_suffix] = sym_unary_suffix, + [anon_sym_DOTsplit] = anon_sym_DOTsplit, + [anon_sym_DOTslice] = anon_sym_DOTslice, + [anon_sym_DOTreverse] = anon_sym_DOTreverse, + [anon_sym_new] = anon_sym_new, + [sym_output_root] = sym_output_root, + [sym_input_root] = sym_input_root, + [anon_sym_DOT] = anon_sym_DOT, + [anon_sym_value] = anon_sym_value, + [anon_sym_scriptPubKey] = anon_sym_scriptPubKey, + [anon_sym_outpointTransactionHash] = anon_sym_outpointTransactionHash, + [anon_sym_outpointIndex] = anon_sym_outpointIndex, + [anon_sym_sigScript] = anon_sym_sigScript, + [anon_sym_int] = anon_sym_int, + [anon_sym_bool] = anon_sym_bool, + [anon_sym_string] = anon_sym_string, + [anon_sym_pubkey] = anon_sym_pubkey, + [anon_sym_sig] = anon_sym_sig, + [anon_sym_datasig] = anon_sym_datasig, + [anon_sym_byte] = anon_sym_byte, + [sym_array_bound] = sym_array_bound, + [anon_sym_true] = anon_sym_true, + [anon_sym_false] = anon_sym_false, + [anon_sym_litras] = anon_sym_litras, + [anon_sym_grains] = anon_sym_grains, + [anon_sym_kas] = anon_sym_kas, + [anon_sym_seconds] = anon_sym_seconds, + [anon_sym_minutes] = anon_sym_minutes, + [anon_sym_hours] = anon_sym_hours, + [anon_sym_days] = anon_sym_days, + [anon_sym_weeks] = anon_sym_weeks, + [sym_number] = sym_number, + [sym_string_literal] = sym_string_literal, + [anon_sym_date] = anon_sym_date, + [sym_hex_literal] = sym_hex_literal, + [anon_sym_this_DOTage] = anon_sym_this_DOTage, + [anon_sym_tx_DOTtime] = anon_sym_tx_DOTtime, + [anon_sym_this_DOTactiveInputIndex] = anon_sym_this_DOTactiveInputIndex, + [anon_sym_this_DOTactiveScriptPubKey] = anon_sym_this_DOTactiveScriptPubKey, + [anon_sym_this_DOTscriptSizeDataPrefix] = anon_sym_this_DOTscriptSizeDataPrefix, + [anon_sym_this_DOTscriptSize] = anon_sym_this_DOTscriptSize, + [anon_sym_tx_DOTinputs_DOTlength] = anon_sym_tx_DOTinputs_DOTlength, + [anon_sym_tx_DOToutputs_DOTlength] = anon_sym_tx_DOToutputs_DOTlength, + [anon_sym_tx_DOTversion] = anon_sym_tx_DOTversion, + [anon_sym_tx_DOTlocktime] = anon_sym_tx_DOTlocktime, + [sym_comment] = sym_comment, + [sym_source_file] = sym_source_file, + [sym_pragma_directive] = sym_pragma_directive, + [sym_pragma_value] = sym_pragma_value, + [sym_version_constraint] = sym_version_constraint, + [sym_version_operator] = sym_version_operator, + [sym_contract_definition] = sym_contract_definition, + [sym_contract_item] = sym_contract_item, + [sym_function_definition] = sym_function_definition, + [sym_constant_definition] = sym_constant_definition, + [sym_contract_field_definition] = sym_contract_field_definition, + [sym_parameter_list] = sym_parameter_list, + [sym_parameter] = sym_parameter, + [sym_return_type_list] = sym_return_type_list, + [sym_block] = sym_block, + [sym_statement] = sym_statement, + [sym_variable_definition] = sym_variable_definition, + [sym_tuple_assignment] = sym_tuple_assignment, + [sym_push_statement] = sym_push_statement, + [sym_function_call_assignment] = sym_function_call_assignment, + [sym_state_function_call_assignment] = sym_state_function_call_assignment, + [sym_typed_binding] = sym_typed_binding, + [sym_state_typed_binding] = sym_state_typed_binding, + [sym_call_statement] = sym_call_statement, + [sym_return_statement] = sym_return_statement, + [sym_assign_statement] = sym_assign_statement, + [sym_time_op_statement] = sym_time_op_statement, + [sym_require_statement] = sym_require_statement, + [sym_require_message] = sym_require_message, + [sym_if_statement] = sym_if_statement, + [sym_for_statement] = sym_for_statement, + [sym_yield_statement] = sym_yield_statement, + [sym_console_statement] = sym_console_statement, + [sym_console_parameter_list] = sym_console_parameter_list, + [sym_console_parameter] = sym_console_parameter, + [sym_expression] = sym_expression, + [sym_logical_or] = sym_logical_or, + [sym_logical_and] = sym_logical_and, + [sym_bit_or] = sym_bit_or, + [sym_bit_xor] = sym_bit_xor, + [sym_bit_and] = sym_bit_and, + [sym_equality] = sym_equality, + [sym_comparison] = sym_comparison, + [sym_term] = sym_term, + [sym_factor] = sym_factor, + [sym_unary] = sym_unary, + [sym_unary_op] = sym_unary_op, + [sym_postfix] = sym_postfix, + [sym_postfix_op] = sym_postfix_op, + [sym_tuple_index] = sym_tuple_index, + [sym_split_call] = sym_split_call, + [sym_slice_call] = sym_slice_call, + [sym_reverse_call] = sym_reverse_call, + [sym_primary] = sym_primary, + [sym_parenthesized] = sym_parenthesized, + [sym_cast] = sym_cast, + [sym_function_call] = sym_function_call, + [sym_expression_list] = sym_expression_list, + [sym_instantiation] = sym_instantiation, + [sym_state_object] = sym_state_object, + [sym_state_entry] = sym_state_entry, + [sym_introspection] = sym_introspection, + [sym_output_field] = sym_output_field, + [sym_output_field_name] = sym_output_field_name, + [sym_input_field] = sym_input_field, + [sym_input_field_name] = sym_input_field_name, + [sym_array] = sym_array, + [sym_modifier] = sym_modifier, + [sym_type_name] = sym_type_name, + [sym_base_type] = sym_base_type, + [sym_array_suffix] = sym_array_suffix, + [sym_array_size] = sym_array_size, + [sym_literal] = sym_literal, + [sym_boolean_literal] = sym_boolean_literal, + [sym_number_literal] = sym_number_literal, + [sym_number_unit] = sym_number_unit, + [sym_date_literal] = sym_date_literal, + [sym_tx_var] = sym_tx_var, + [sym_nullary_op] = sym_nullary_op, + [aux_sym_source_file_repeat1] = aux_sym_source_file_repeat1, + [aux_sym_contract_definition_repeat1] = aux_sym_contract_definition_repeat1, + [aux_sym_function_definition_repeat1] = aux_sym_function_definition_repeat1, + [aux_sym_parameter_list_repeat1] = aux_sym_parameter_list_repeat1, + [aux_sym_return_type_list_repeat1] = aux_sym_return_type_list_repeat1, + [aux_sym_variable_definition_repeat1] = aux_sym_variable_definition_repeat1, + [aux_sym_function_call_assignment_repeat1] = aux_sym_function_call_assignment_repeat1, + [aux_sym_state_function_call_assignment_repeat1] = aux_sym_state_function_call_assignment_repeat1, + [aux_sym_console_parameter_list_repeat1] = aux_sym_console_parameter_list_repeat1, + [aux_sym_logical_or_repeat1] = aux_sym_logical_or_repeat1, + [aux_sym_logical_and_repeat1] = aux_sym_logical_and_repeat1, + [aux_sym_bit_or_repeat1] = aux_sym_bit_or_repeat1, + [aux_sym_bit_xor_repeat1] = aux_sym_bit_xor_repeat1, + [aux_sym_bit_and_repeat1] = aux_sym_bit_and_repeat1, + [aux_sym_equality_repeat1] = aux_sym_equality_repeat1, + [aux_sym_comparison_repeat1] = aux_sym_comparison_repeat1, + [aux_sym_term_repeat1] = aux_sym_term_repeat1, + [aux_sym_factor_repeat1] = aux_sym_factor_repeat1, + [aux_sym_unary_repeat1] = aux_sym_unary_repeat1, + [aux_sym_postfix_repeat1] = aux_sym_postfix_repeat1, + [aux_sym_expression_list_repeat1] = aux_sym_expression_list_repeat1, + [aux_sym_state_object_repeat1] = aux_sym_state_object_repeat1, + [aux_sym_type_name_repeat1] = aux_sym_type_name_repeat1, +}; + +static const TSSymbolMetadata ts_symbol_metadata[] = { + [ts_builtin_sym_end] = { + .visible = false, + .named = true, + }, + [sym_identifier] = { + .visible = true, + .named = true, + }, + [anon_sym_pragma] = { + .visible = true, + .named = false, + }, + [anon_sym_silverscript] = { + .visible = true, + .named = false, + }, + [anon_sym_SEMI] = { + .visible = true, + .named = false, + }, + [anon_sym_CARET] = { + .visible = true, + .named = false, + }, + [anon_sym_TILDE] = { + .visible = true, + .named = false, + }, + [anon_sym_GT_EQ] = { + .visible = true, + .named = false, + }, + [anon_sym_GT] = { + .visible = true, + .named = false, + }, + [anon_sym_LT_EQ] = { + .visible = true, + .named = false, + }, + [anon_sym_LT] = { + .visible = true, + .named = false, + }, + [anon_sym_EQ] = { + .visible = true, + .named = false, + }, + [sym_version_literal] = { + .visible = true, + .named = true, + }, + [anon_sym_contract] = { + .visible = true, + .named = false, + }, + [anon_sym_LBRACE] = { + .visible = true, + .named = false, + }, + [anon_sym_RBRACE] = { + .visible = true, + .named = false, + }, + [anon_sym_entrypoint] = { + .visible = true, + .named = false, + }, + [anon_sym_function] = { + .visible = true, + .named = false, + }, + [anon_sym_constant] = { + .visible = true, + .named = false, + }, + [anon_sym_LPAREN] = { + .visible = true, + .named = false, + }, + [anon_sym_COMMA] = { + .visible = true, + .named = false, + }, + [anon_sym_RPAREN] = { + .visible = true, + .named = false, + }, + [anon_sym_COLON] = { + .visible = true, + .named = false, + }, + [anon_sym_DOTpush] = { + .visible = true, + .named = false, + }, + [anon_sym_return] = { + .visible = true, + .named = false, + }, + [anon_sym_require] = { + .visible = true, + .named = false, + }, + [anon_sym_if] = { + .visible = true, + .named = false, + }, + [anon_sym_else] = { + .visible = true, + .named = false, + }, + [anon_sym_for] = { + .visible = true, + .named = false, + }, + [anon_sym_yield] = { + .visible = true, + .named = false, + }, + [anon_sym_console_DOTlog] = { + .visible = true, + .named = false, + }, + [anon_sym_PIPE_PIPE] = { + .visible = true, + .named = false, + }, + [anon_sym_AMP_AMP] = { + .visible = true, + .named = false, + }, + [anon_sym_PIPE] = { + .visible = true, + .named = false, + }, + [anon_sym_AMP] = { + .visible = true, + .named = false, + }, + [anon_sym_EQ_EQ] = { + .visible = true, + .named = false, + }, + [anon_sym_BANG_EQ] = { + .visible = true, + .named = false, + }, + [anon_sym_PLUS] = { + .visible = true, + .named = false, + }, + [anon_sym_DASH] = { + .visible = true, + .named = false, + }, + [anon_sym_STAR] = { + .visible = true, + .named = false, + }, + [anon_sym_SLASH] = { + .visible = true, + .named = false, + }, + [anon_sym_PERCENT] = { + .visible = true, + .named = false, + }, + [anon_sym_BANG] = { + .visible = true, + .named = false, + }, + [anon_sym_LBRACK] = { + .visible = true, + .named = false, + }, + [anon_sym_RBRACK] = { + .visible = true, + .named = false, + }, + [sym_unary_suffix] = { + .visible = true, + .named = true, + }, + [anon_sym_DOTsplit] = { + .visible = true, + .named = false, + }, + [anon_sym_DOTslice] = { + .visible = true, + .named = false, + }, + [anon_sym_DOTreverse] = { + .visible = true, + .named = false, + }, + [anon_sym_new] = { + .visible = true, + .named = false, + }, + [sym_output_root] = { + .visible = true, + .named = true, + }, + [sym_input_root] = { + .visible = true, + .named = true, + }, + [anon_sym_DOT] = { + .visible = true, + .named = false, + }, + [anon_sym_value] = { + .visible = true, + .named = false, + }, + [anon_sym_scriptPubKey] = { + .visible = true, + .named = false, + }, + [anon_sym_outpointTransactionHash] = { + .visible = true, + .named = false, + }, + [anon_sym_outpointIndex] = { + .visible = true, + .named = false, + }, + [anon_sym_sigScript] = { + .visible = true, + .named = false, + }, + [anon_sym_int] = { + .visible = true, + .named = false, + }, + [anon_sym_bool] = { + .visible = true, + .named = false, + }, + [anon_sym_string] = { + .visible = true, + .named = false, + }, + [anon_sym_pubkey] = { + .visible = true, + .named = false, + }, + [anon_sym_sig] = { + .visible = true, + .named = false, + }, + [anon_sym_datasig] = { + .visible = true, + .named = false, + }, + [anon_sym_byte] = { + .visible = true, + .named = false, + }, + [sym_array_bound] = { + .visible = true, + .named = true, + }, + [anon_sym_true] = { + .visible = true, + .named = false, + }, + [anon_sym_false] = { + .visible = true, + .named = false, + }, + [anon_sym_litras] = { + .visible = true, + .named = false, + }, + [anon_sym_grains] = { + .visible = true, + .named = false, + }, + [anon_sym_kas] = { + .visible = true, + .named = false, + }, + [anon_sym_seconds] = { + .visible = true, + .named = false, + }, + [anon_sym_minutes] = { + .visible = true, + .named = false, + }, + [anon_sym_hours] = { + .visible = true, + .named = false, + }, + [anon_sym_days] = { + .visible = true, + .named = false, + }, + [anon_sym_weeks] = { + .visible = true, + .named = false, + }, + [sym_number] = { + .visible = true, + .named = true, + }, + [sym_string_literal] = { + .visible = true, + .named = true, + }, + [anon_sym_date] = { + .visible = true, + .named = false, + }, + [sym_hex_literal] = { + .visible = true, + .named = true, + }, + [anon_sym_this_DOTage] = { + .visible = true, + .named = false, + }, + [anon_sym_tx_DOTtime] = { + .visible = true, + .named = false, + }, + [anon_sym_this_DOTactiveInputIndex] = { + .visible = true, + .named = false, + }, + [anon_sym_this_DOTactiveScriptPubKey] = { + .visible = true, + .named = false, + }, + [anon_sym_this_DOTscriptSizeDataPrefix] = { + .visible = true, + .named = false, + }, + [anon_sym_this_DOTscriptSize] = { + .visible = true, + .named = false, + }, + [anon_sym_tx_DOTinputs_DOTlength] = { + .visible = true, + .named = false, + }, + [anon_sym_tx_DOToutputs_DOTlength] = { + .visible = true, + .named = false, + }, + [anon_sym_tx_DOTversion] = { + .visible = true, + .named = false, + }, + [anon_sym_tx_DOTlocktime] = { + .visible = true, + .named = false, + }, + [sym_comment] = { + .visible = true, + .named = true, + }, + [sym_source_file] = { + .visible = true, + .named = true, + }, + [sym_pragma_directive] = { + .visible = true, + .named = true, + }, + [sym_pragma_value] = { + .visible = true, + .named = true, + }, + [sym_version_constraint] = { + .visible = true, + .named = true, + }, + [sym_version_operator] = { + .visible = true, + .named = true, + }, + [sym_contract_definition] = { + .visible = true, + .named = true, + }, + [sym_contract_item] = { + .visible = true, + .named = true, + }, + [sym_function_definition] = { + .visible = true, + .named = true, + }, + [sym_constant_definition] = { + .visible = true, + .named = true, + }, + [sym_contract_field_definition] = { + .visible = true, + .named = true, + }, + [sym_parameter_list] = { + .visible = true, + .named = true, + }, + [sym_parameter] = { + .visible = true, + .named = true, + }, + [sym_return_type_list] = { + .visible = true, + .named = true, + }, + [sym_block] = { + .visible = true, + .named = true, + }, + [sym_statement] = { + .visible = true, + .named = true, + }, + [sym_variable_definition] = { + .visible = true, + .named = true, + }, + [sym_tuple_assignment] = { + .visible = true, + .named = true, + }, + [sym_push_statement] = { + .visible = true, + .named = true, + }, + [sym_function_call_assignment] = { + .visible = true, + .named = true, + }, + [sym_state_function_call_assignment] = { + .visible = true, + .named = true, + }, + [sym_typed_binding] = { + .visible = true, + .named = true, + }, + [sym_state_typed_binding] = { + .visible = true, + .named = true, + }, + [sym_call_statement] = { + .visible = true, + .named = true, + }, + [sym_return_statement] = { + .visible = true, + .named = true, + }, + [sym_assign_statement] = { + .visible = true, + .named = true, + }, + [sym_time_op_statement] = { + .visible = true, + .named = true, + }, + [sym_require_statement] = { + .visible = true, + .named = true, + }, + [sym_require_message] = { + .visible = true, + .named = true, + }, + [sym_if_statement] = { + .visible = true, + .named = true, + }, + [sym_for_statement] = { + .visible = true, + .named = true, + }, + [sym_yield_statement] = { + .visible = true, + .named = true, + }, + [sym_console_statement] = { + .visible = true, + .named = true, + }, + [sym_console_parameter_list] = { + .visible = true, + .named = true, + }, + [sym_console_parameter] = { + .visible = true, + .named = true, + }, + [sym_expression] = { + .visible = true, + .named = true, + }, + [sym_logical_or] = { + .visible = true, + .named = true, + }, + [sym_logical_and] = { + .visible = true, + .named = true, + }, + [sym_bit_or] = { + .visible = true, + .named = true, + }, + [sym_bit_xor] = { + .visible = true, + .named = true, + }, + [sym_bit_and] = { + .visible = true, + .named = true, + }, + [sym_equality] = { + .visible = true, + .named = true, + }, + [sym_comparison] = { + .visible = true, + .named = true, + }, + [sym_term] = { + .visible = true, + .named = true, + }, + [sym_factor] = { + .visible = true, + .named = true, + }, + [sym_unary] = { + .visible = true, + .named = true, + }, + [sym_unary_op] = { + .visible = true, + .named = true, + }, + [sym_postfix] = { + .visible = true, + .named = true, + }, + [sym_postfix_op] = { + .visible = true, + .named = true, + }, + [sym_tuple_index] = { + .visible = true, + .named = true, + }, + [sym_split_call] = { + .visible = true, + .named = true, + }, + [sym_slice_call] = { + .visible = true, + .named = true, + }, + [sym_reverse_call] = { + .visible = true, + .named = true, + }, + [sym_primary] = { + .visible = true, + .named = true, + }, + [sym_parenthesized] = { + .visible = true, + .named = true, + }, + [sym_cast] = { + .visible = true, + .named = true, + }, + [sym_function_call] = { + .visible = true, + .named = true, + }, + [sym_expression_list] = { + .visible = true, + .named = true, + }, + [sym_instantiation] = { + .visible = true, + .named = true, + }, + [sym_state_object] = { + .visible = true, + .named = true, + }, + [sym_state_entry] = { + .visible = true, + .named = true, + }, + [sym_introspection] = { + .visible = true, + .named = true, + }, + [sym_output_field] = { + .visible = true, + .named = true, + }, + [sym_output_field_name] = { + .visible = true, + .named = true, + }, + [sym_input_field] = { + .visible = true, + .named = true, + }, + [sym_input_field_name] = { + .visible = true, + .named = true, + }, + [sym_array] = { + .visible = true, + .named = true, + }, + [sym_modifier] = { + .visible = true, + .named = true, + }, + [sym_type_name] = { + .visible = true, + .named = true, + }, + [sym_base_type] = { + .visible = true, + .named = true, + }, + [sym_array_suffix] = { + .visible = true, + .named = true, + }, + [sym_array_size] = { + .visible = true, + .named = true, + }, + [sym_literal] = { + .visible = true, + .named = true, + }, + [sym_boolean_literal] = { + .visible = true, + .named = true, + }, + [sym_number_literal] = { + .visible = true, + .named = true, + }, + [sym_number_unit] = { + .visible = true, + .named = true, + }, + [sym_date_literal] = { + .visible = true, + .named = true, + }, + [sym_tx_var] = { + .visible = true, + .named = true, + }, + [sym_nullary_op] = { + .visible = true, + .named = true, + }, + [aux_sym_source_file_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_contract_definition_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_function_definition_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_parameter_list_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_return_type_list_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_variable_definition_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_function_call_assignment_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_state_function_call_assignment_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_console_parameter_list_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_logical_or_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_logical_and_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_bit_or_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_bit_xor_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_bit_and_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_equality_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_comparison_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_term_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_factor_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_unary_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_postfix_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_expression_list_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_state_object_repeat1] = { + .visible = false, + .named = false, + }, + [aux_sym_type_name_repeat1] = { + .visible = false, + .named = false, + }, +}; + +enum ts_field_identifiers { + field_field = 1, + field_index = 2, + field_name = 3, + field_root = 4, + field_value = 5, +}; + +static const char * const ts_field_names[] = { + [0] = NULL, + [field_field] = "field", + [field_index] = "index", + [field_name] = "name", + [field_root] = "root", + [field_value] = "value", +}; + +static const TSMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = { + [1] = {.index = 0, .length = 1}, + [2] = {.index = 1, .length = 2}, + [3] = {.index = 3, .length = 1}, + [4] = {.index = 4, .length = 2}, + [5] = {.index = 6, .length = 3}, + [6] = {.index = 9, .length = 2}, + [7] = {.index = 11, .length = 1}, +}; + +static const TSFieldMapEntry ts_field_map_entries[] = { + [0] = + {field_name, 1}, + [1] = + {field_name, 1}, + {field_value, 3}, + [3] = + {field_name, 2}, + [4] = + {field_name, 2}, + {field_value, 4}, + [6] = + {field_field, 2}, + {field_index, 1}, + {field_root, 0}, + [9] = + {field_name, 0}, + {field_value, 2}, + [11] = + {field_name, 0}, +}; + +static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = { + [0] = {0}, +}; + +static const uint16_t ts_non_terminal_alias_map[] = { + 0, +}; + +static const TSStateId ts_primary_state_ids[STATE_COUNT] = { + [0] = 0, + [1] = 1, + [2] = 2, + [3] = 3, + [4] = 4, + [5] = 5, + [6] = 6, + [7] = 7, + [8] = 8, + [9] = 9, + [10] = 10, + [11] = 11, + [12] = 12, + [13] = 13, + [14] = 14, + [15] = 15, + [16] = 16, + [17] = 17, + [18] = 18, + [19] = 19, + [20] = 20, + [21] = 21, + [22] = 22, + [23] = 23, + [24] = 24, + [25] = 25, + [26] = 26, + [27] = 27, + [28] = 24, + [29] = 29, + [30] = 30, + [31] = 31, + [32] = 32, + [33] = 33, + [34] = 34, + [35] = 35, + [36] = 36, + [37] = 37, + [38] = 38, + [39] = 39, + [40] = 40, + [41] = 41, + [42] = 42, + [43] = 43, + [44] = 44, + [45] = 45, + [46] = 46, + [47] = 47, + [48] = 48, + [49] = 49, + [50] = 50, + [51] = 51, + [52] = 52, + [53] = 53, + [54] = 54, + [55] = 55, + [56] = 56, + [57] = 57, + [58] = 58, + [59] = 59, + [60] = 60, + [61] = 61, + [62] = 62, + [63] = 63, + [64] = 64, + [65] = 65, + [66] = 66, + [67] = 67, + [68] = 68, + [69] = 69, + [70] = 70, + [71] = 71, + [72] = 72, + [73] = 73, + [74] = 74, + [75] = 75, + [76] = 76, + [77] = 77, + [78] = 78, + [79] = 79, + [80] = 80, + [81] = 81, + [82] = 82, + [83] = 83, + [84] = 84, + [85] = 85, + [86] = 86, + [87] = 87, + [88] = 88, + [89] = 89, + [90] = 90, + [91] = 91, + [92] = 92, + [93] = 93, + [94] = 94, + [95] = 95, + [96] = 96, + [97] = 97, + [98] = 98, + [99] = 99, + [100] = 100, + [101] = 101, + [102] = 102, + [103] = 103, + [104] = 104, + [105] = 105, + [106] = 106, + [107] = 107, + [108] = 108, + [109] = 109, + [110] = 110, + [111] = 111, + [112] = 112, + [113] = 113, + [114] = 114, + [115] = 115, + [116] = 116, + [117] = 117, + [118] = 118, + [119] = 119, + [120] = 120, + [121] = 121, + [122] = 122, + [123] = 123, + [124] = 124, + [125] = 125, + [126] = 126, + [127] = 127, + [128] = 128, + [129] = 129, + [130] = 130, + [131] = 131, + [132] = 132, + [133] = 133, + [134] = 134, + [135] = 135, + [136] = 136, + [137] = 137, + [138] = 138, + [139] = 139, + [140] = 140, + [141] = 141, + [142] = 142, + [143] = 143, + [144] = 144, + [145] = 145, + [146] = 146, + [147] = 147, + [148] = 148, + [149] = 149, + [150] = 150, + [151] = 151, + [152] = 152, + [153] = 153, + [154] = 154, + [155] = 155, + [156] = 156, + [157] = 157, + [158] = 158, + [159] = 159, + [160] = 160, + [161] = 161, + [162] = 162, + [163] = 163, + [164] = 164, + [165] = 165, + [166] = 166, + [167] = 167, + [168] = 168, + [169] = 169, + [170] = 170, + [171] = 171, + [172] = 172, + [173] = 173, + [174] = 174, + [175] = 175, + [176] = 176, + [177] = 177, + [178] = 178, + [179] = 179, + [180] = 180, + [181] = 181, + [182] = 182, + [183] = 183, + [184] = 184, + [185] = 185, + [186] = 186, + [187] = 187, + [188] = 188, + [189] = 189, + [190] = 190, + [191] = 191, + [192] = 192, + [193] = 193, + [194] = 194, + [195] = 195, + [196] = 196, + [197] = 197, + [198] = 198, + [199] = 199, + [200] = 200, + [201] = 201, + [202] = 202, + [203] = 203, + [204] = 204, + [205] = 205, + [206] = 206, + [207] = 207, + [208] = 208, + [209] = 209, + [210] = 210, + [211] = 211, + [212] = 212, + [213] = 213, + [214] = 214, + [215] = 215, + [216] = 216, + [217] = 217, + [218] = 218, + [219] = 219, + [220] = 220, + [221] = 221, + [222] = 222, + [223] = 223, + [224] = 224, + [225] = 225, + [226] = 226, + [227] = 227, + [228] = 228, + [229] = 229, + [230] = 230, + [231] = 231, + [232] = 232, + [233] = 233, + [234] = 234, + [235] = 235, + [236] = 236, + [237] = 237, + [238] = 238, + [239] = 239, + [240] = 240, + [241] = 241, + [242] = 242, + [243] = 243, + [244] = 244, + [245] = 245, + [246] = 246, + [247] = 247, + [248] = 248, + [249] = 249, + [250] = 250, + [251] = 251, + [252] = 252, + [253] = 253, + [254] = 254, + [255] = 255, + [256] = 256, + [257] = 257, + [258] = 258, + [259] = 259, + [260] = 260, + [261] = 261, + [262] = 262, + [263] = 263, + [264] = 264, + [265] = 265, + [266] = 266, + [267] = 267, + [268] = 268, + [269] = 269, + [270] = 270, + [271] = 271, + [272] = 272, + [273] = 273, + [274] = 274, + [275] = 275, + [276] = 276, + [277] = 277, + [278] = 278, + [279] = 279, + [280] = 280, + [281] = 281, + [282] = 282, + [283] = 283, + [284] = 284, + [285] = 285, + [286] = 286, + [287] = 287, + [288] = 288, + [289] = 289, + [290] = 290, + [291] = 291, + [292] = 292, + [293] = 293, + [294] = 294, + [295] = 295, + [296] = 296, + [297] = 297, + [298] = 298, + [299] = 299, + [300] = 300, + [301] = 301, + [302] = 302, + [303] = 303, + [304] = 304, + [305] = 305, + [306] = 306, + [307] = 307, + [308] = 308, + [309] = 309, + [310] = 310, + [311] = 311, + [312] = 312, + [313] = 95, + [314] = 314, + [315] = 315, + [316] = 316, + [317] = 317, + [318] = 318, + [319] = 319, + [320] = 320, + [321] = 321, + [322] = 322, + [323] = 323, + [324] = 324, + [325] = 325, + [326] = 326, + [327] = 327, + [328] = 328, + [329] = 329, + [330] = 330, + [331] = 331, + [332] = 332, + [333] = 333, + [334] = 334, + [335] = 335, + [336] = 336, + [337] = 337, + [338] = 338, + [339] = 339, + [340] = 340, + [341] = 341, + [342] = 342, + [343] = 343, + [344] = 344, + [345] = 345, + [346] = 346, + [347] = 347, + [348] = 348, + [349] = 349, + [350] = 350, + [351] = 351, + [352] = 352, + [353] = 353, + [354] = 354, + [355] = 355, + [356] = 356, + [357] = 357, + [358] = 358, + [359] = 359, + [360] = 360, + [361] = 361, + [362] = 362, + [363] = 363, + [364] = 364, + [365] = 365, + [366] = 366, + [367] = 367, + [368] = 368, + [369] = 369, + [370] = 370, + [371] = 371, + [372] = 372, + [373] = 373, + [374] = 374, + [375] = 375, + [376] = 376, + [377] = 377, + [378] = 378, + [379] = 379, + [380] = 380, + [381] = 381, + [382] = 382, + [383] = 383, + [384] = 384, + [385] = 385, + [386] = 355, + [387] = 387, + [388] = 388, +}; + +static bool ts_lex(TSLexer *lexer, TSStateId state) { + START_LEXER(); + eof = lexer->eof(lexer); + switch (state) { + case 0: + if (eof) ADVANCE(136); + ADVANCE_MAP( + '!', 168, + '"', 5, + '%', 166, + '&', 158, + '\'', 6, + '(', 149, + ')', 151, + '*', 164, + '+', 161, + ',', 150, + '-', 163, + '.', 178, + '/', 165, + '0', 181, + ':', 152, + ';', 137, + '<', 143, + '=', 145, + '>', 141, + '[', 169, + ']', 170, + '^', 138, + 'c', 208, + 't', 202, + '{', 147, + '|', 157, + '}', 148, + '~', 139, + ); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(0); + if (('1' <= lookahead && lookahead <= '9')) ADVANCE(179); + if (('A' <= lookahead && lookahead <= 'Z') || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 1: + ADVANCE_MAP( + '!', 13, + '%', 166, + '&', 158, + '(', 149, + ')', 151, + '*', 164, + '+', 161, + ',', 150, + '-', 162, + '.', 71, + '/', 165, + ';', 137, + '<', 143, + '=', 14, + '>', 141, + '[', 169, + ']', 170, + '^', 138, + '|', 157, + '}', 148, + ); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(1); + if (('1' <= lookahead && lookahead <= '9')) ADVANCE(180); + if (('A' <= lookahead && lookahead <= 'Z') || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 2: + ADVANCE_MAP( + '!', 167, + '"', 5, + '\'', 6, + '(', 149, + ')', 151, + '-', 163, + '.', 177, + '/', 8, + '0', 181, + '[', 169, + ']', 170, + 't', 203, + '{', 147, + ); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(2); + if (('1' <= lookahead && lookahead <= '9')) ADVANCE(182); + if (('A' <= lookahead && lookahead <= 'Z') || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 3: + ADVANCE_MAP( + '!', 167, + '"', 5, + '\'', 6, + '(', 149, + ',', 150, + '-', 163, + '.', 89, + '/', 8, + '0', 181, + ':', 152, + ';', 137, + '=', 144, + '[', 169, + 't', 202, + '{', 147, + ); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(3); + if (('1' <= lookahead && lookahead <= '9')) ADVANCE(182); + if (('A' <= lookahead && lookahead <= 'Z') || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 4: + if (lookahead == '"') ADVANCE(5); + if (lookahead == '\'') ADVANCE(6); + if (lookahead == ')') ADVANCE(151); + if (lookahead == '-') ADVANCE(130); + if (lookahead == '/') ADVANCE(8); + if (lookahead == '0') ADVANCE(181); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(4); + if (('1' <= lookahead && lookahead <= '9')) ADVANCE(182); + if (('A' <= lookahead && lookahead <= 'Z') || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 5: + if (lookahead == '"') ADVANCE(184); + if (lookahead == '\\') ADVANCE(134); + if (lookahead != 0 && + lookahead != '\n') ADVANCE(5); + END_STATE(); + case 6: + if (lookahead == '\'') ADVANCE(184); + if (lookahead == '\\') ADVANCE(135); + if (lookahead != 0 && + lookahead != '\n') ADVANCE(6); + END_STATE(); + case 7: + ADVANCE_MAP( + '(', 149, + '/', 8, + ';', 137, + '<', 143, + '=', 144, + '>', 141, + '^', 138, + 'c', 208, + '{', 147, + '}', 148, + '~', 139, + ); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(7); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(11); + if (('A' <= lookahead && lookahead <= 'Z') || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 8: + if (lookahead == '*') ADVANCE(10); + if (lookahead == '/') ADVANCE(215); + END_STATE(); + case 9: + if (lookahead == '*') ADVANCE(9); + if (lookahead == '/') ADVANCE(214); + if (lookahead != 0) ADVANCE(10); + END_STATE(); + case 10: + if (lookahead == '*') ADVANCE(9); + if (lookahead != 0) ADVANCE(10); + END_STATE(); + case 11: + if (lookahead == '.') ADVANCE(133); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(11); + END_STATE(); + case 12: + if (lookahead == '.') ADVANCE(132); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(12); + END_STATE(); + case 13: + if (lookahead == '=') ADVANCE(160); + END_STATE(); + case 14: + if (lookahead == '=') ADVANCE(159); + END_STATE(); + case 15: + if (lookahead == 'I') ADVANCE(82); + END_STATE(); + case 16: + if (lookahead == 'I') ADVANCE(85); + if (lookahead == 'S') ADVANCE(31); + END_STATE(); + case 17: + if (lookahead == 'K') ADVANCE(43); + END_STATE(); + case 18: + if (lookahead == 'P') ADVANCE(119); + END_STATE(); + case 19: + if (lookahead == 'P') ADVANCE(98); + END_STATE(); + case 20: + if (lookahead == 'S') ADVANCE(59); + END_STATE(); + case 21: + if (lookahead == 'a') ADVANCE(29); + if (lookahead == 's') ADVANCE(27); + END_STATE(); + case 22: + if (lookahead == 'a') ADVANCE(19); + END_STATE(); + case 23: + if (lookahead == 'a') ADVANCE(28); + if (lookahead == 's') ADVANCE(27); + END_STATE(); + case 24: + if (lookahead == 'a') ADVANCE(110); + END_STATE(); + case 25: + if (lookahead == 'b') ADVANCE(17); + END_STATE(); + case 26: + if (lookahead == 'c') ADVANCE(70); + END_STATE(); + case 27: + if (lookahead == 'c') ADVANCE(97); + END_STATE(); + case 28: + if (lookahead == 'c') ADVANCE(112); + END_STATE(); + case 29: + if (lookahead == 'c') ADVANCE(112); + if (lookahead == 'g') ADVANCE(38); + END_STATE(); + case 30: + if (lookahead == 'c') ADVANCE(45); + END_STATE(); + case 31: + if (lookahead == 'c') ADVANCE(99); + END_STATE(); + case 32: + if (lookahead == 'd') ADVANCE(42); + END_STATE(); + case 33: + if (lookahead == 'e') ADVANCE(79); + END_STATE(); + case 34: + if (lookahead == 'e') ADVANCE(124); + END_STATE(); + case 35: + if (lookahead == 'e') ADVANCE(95); + END_STATE(); + case 36: + if (lookahead == 'e') ADVANCE(187); + END_STATE(); + case 37: + if (lookahead == 'e') ADVANCE(174); + END_STATE(); + case 38: + if (lookahead == 'e') ADVANCE(186); + END_STATE(); + case 39: + if (lookahead == 'e') ADVANCE(16); + END_STATE(); + case 40: + if (lookahead == 'e') ADVANCE(195); + END_STATE(); + case 41: + if (lookahead == 'e') ADVANCE(191); + END_STATE(); + case 42: + if (lookahead == 'e') ADVANCE(126); + END_STATE(); + case 43: + if (lookahead == 'e') ADVANCE(128); + END_STATE(); + case 44: + if (lookahead == 'e') ADVANCE(49); + END_STATE(); + case 45: + if (lookahead == 'e') ADVANCE(173); + END_STATE(); + case 46: + if (lookahead == 'e') ADVANCE(96); + END_STATE(); + case 47: + if (lookahead == 'e') ADVANCE(83); + END_STATE(); + case 48: + if (lookahead == 'e') ADVANCE(84); + END_STATE(); + case 49: + if (lookahead == 'f') ADVANCE(64); + END_STATE(); + case 50: + if (lookahead == 'g') ADVANCE(109); + END_STATE(); + case 51: + if (lookahead == 'g') ADVANCE(154); + END_STATE(); + case 52: + if (lookahead == 'g') ADVANCE(111); + END_STATE(); + case 53: + if (lookahead == 'g') ADVANCE(114); + END_STATE(); + case 54: + if (lookahead == 'h') ADVANCE(153); + END_STATE(); + case 55: + if (lookahead == 'h') ADVANCE(171); + END_STATE(); + case 56: + if (lookahead == 'h') ADVANCE(192); + END_STATE(); + case 57: + if (lookahead == 'h') ADVANCE(193); + END_STATE(); + case 58: + if (lookahead == 'i') ADVANCE(77); + END_STATE(); + case 59: + if (lookahead == 'i') ADVANCE(129); + END_STATE(); + case 60: + if (lookahead == 'i') ADVANCE(80); + if (lookahead == 'l') ADVANCE(86); + if (lookahead == 'o') ADVANCE(120); + if (lookahead == 't') ADVANCE(58); + if (lookahead == 'v') ADVANCE(46); + END_STATE(); + case 61: + if (lookahead == 'i') ADVANCE(80); + if (lookahead == 'l') ADVANCE(86); + if (lookahead == 'o') ADVANCE(120); + if (lookahead == 'v') ADVANCE(46); + END_STATE(); + case 62: + if (lookahead == 'i') ADVANCE(88); + END_STATE(); + case 63: + if (lookahead == 'i') ADVANCE(90); + END_STATE(); + case 64: + if (lookahead == 'i') ADVANCE(127); + END_STATE(); + case 65: + if (lookahead == 'i') ADVANCE(30); + END_STATE(); + case 66: + if (lookahead == 'i') ADVANCE(108); + END_STATE(); + case 67: + if (lookahead == 'i') ADVANCE(125); + END_STATE(); + case 68: + if (lookahead == 'i') ADVANCE(78); + END_STATE(); + case 69: + if (lookahead == 'i') ADVANCE(91); + END_STATE(); + case 70: + if (lookahead == 'k') ADVANCE(116); + END_STATE(); + case 71: + if (lookahead == 'l') ADVANCE(33); + if (lookahead == 'r') ADVANCE(34); + if (lookahead == 's') ADVANCE(73); + END_STATE(); + case 72: + if (lookahead == 'l') ADVANCE(87); + END_STATE(); + case 73: + if (lookahead == 'l') ADVANCE(65); + if (lookahead == 'p') ADVANCE(74); + END_STATE(); + case 74: + if (lookahead == 'l') ADVANCE(66); + END_STATE(); + case 75: + if (lookahead == 'l') ADVANCE(47); + END_STATE(); + case 76: + if (lookahead == 'l') ADVANCE(48); + END_STATE(); + case 77: + if (lookahead == 'm') ADVANCE(36); + END_STATE(); + case 78: + if (lookahead == 'm') ADVANCE(40); + END_STATE(); + case 79: + if (lookahead == 'n') ADVANCE(50); + END_STATE(); + case 80: + if (lookahead == 'n') ADVANCE(92); + END_STATE(); + case 81: + if (lookahead == 'n') ADVANCE(194); + END_STATE(); + case 82: + if (lookahead == 'n') ADVANCE(32); + END_STATE(); + case 83: + if (lookahead == 'n') ADVANCE(52); + END_STATE(); + case 84: + if (lookahead == 'n') ADVANCE(53); + END_STATE(); + case 85: + if (lookahead == 'n') ADVANCE(94); + END_STATE(); + case 86: + if (lookahead == 'o') ADVANCE(26); + END_STATE(); + case 87: + if (lookahead == 'o') ADVANCE(51); + END_STATE(); + case 88: + if (lookahead == 'o') ADVANCE(81); + END_STATE(); + case 89: + if (lookahead == 'p') ADVANCE(118); + END_STATE(); + case 90: + if (lookahead == 'p') ADVANCE(105); + END_STATE(); + case 91: + if (lookahead == 'p') ADVANCE(107); + END_STATE(); + case 92: + if (lookahead == 'p') ADVANCE(121); + END_STATE(); + case 93: + if (lookahead == 'p') ADVANCE(122); + END_STATE(); + case 94: + if (lookahead == 'p') ADVANCE(123); + END_STATE(); + case 95: + if (lookahead == 'r') ADVANCE(104); + END_STATE(); + case 96: + if (lookahead == 'r') ADVANCE(103); + END_STATE(); + case 97: + if (lookahead == 'r') ADVANCE(63); + END_STATE(); + case 98: + if (lookahead == 'r') ADVANCE(44); + END_STATE(); + case 99: + if (lookahead == 'r') ADVANCE(69); + END_STATE(); + case 100: + if (lookahead == 's') ADVANCE(54); + END_STATE(); + case 101: + if (lookahead == 's') ADVANCE(176); + END_STATE(); + case 102: + if (lookahead == 's') ADVANCE(175); + END_STATE(); + case 103: + if (lookahead == 's') ADVANCE(62); + END_STATE(); + case 104: + if (lookahead == 's') ADVANCE(37); + END_STATE(); + case 105: + if (lookahead == 't') ADVANCE(20); + END_STATE(); + case 106: + if (lookahead == 't') ADVANCE(15); + END_STATE(); + case 107: + if (lookahead == 't') ADVANCE(18); + END_STATE(); + case 108: + if (lookahead == 't') ADVANCE(172); + END_STATE(); + case 109: + if (lookahead == 't') ADVANCE(55); + END_STATE(); + case 110: + if (lookahead == 't') ADVANCE(22); + END_STATE(); + case 111: + if (lookahead == 't') ADVANCE(56); + END_STATE(); + case 112: + if (lookahead == 't') ADVANCE(67); + END_STATE(); + case 113: + if (lookahead == 't') ADVANCE(101); + END_STATE(); + case 114: + if (lookahead == 't') ADVANCE(57); + END_STATE(); + case 115: + if (lookahead == 't') ADVANCE(102); + END_STATE(); + case 116: + if (lookahead == 't') ADVANCE(68); + END_STATE(); + case 117: + if (lookahead == 't') ADVANCE(93); + END_STATE(); + case 118: + if (lookahead == 'u') ADVANCE(100); + END_STATE(); + case 119: + if (lookahead == 'u') ADVANCE(25); + END_STATE(); + case 120: + if (lookahead == 'u') ADVANCE(117); + END_STATE(); + case 121: + if (lookahead == 'u') ADVANCE(113); + END_STATE(); + case 122: + if (lookahead == 'u') ADVANCE(115); + END_STATE(); + case 123: + if (lookahead == 'u') ADVANCE(106); + END_STATE(); + case 124: + if (lookahead == 'v') ADVANCE(35); + END_STATE(); + case 125: + if (lookahead == 'v') ADVANCE(39); + END_STATE(); + case 126: + if (lookahead == 'x') ADVANCE(188); + END_STATE(); + case 127: + if (lookahead == 'x') ADVANCE(190); + END_STATE(); + case 128: + if (lookahead == 'y') ADVANCE(189); + END_STATE(); + case 129: + if (lookahead == 'z') ADVANCE(41); + END_STATE(); + case 130: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(182); + END_STATE(); + case 131: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(183); + END_STATE(); + case 132: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(146); + END_STATE(); + case 133: + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(12); + END_STATE(); + case 134: + if (lookahead != 0 && + lookahead != '\n') ADVANCE(5); + END_STATE(); + case 135: + if (lookahead != 0 && + lookahead != '\n') ADVANCE(6); + END_STATE(); + case 136: + ACCEPT_TOKEN(ts_builtin_sym_end); + END_STATE(); + case 137: + ACCEPT_TOKEN(anon_sym_SEMI); + END_STATE(); + case 138: + ACCEPT_TOKEN(anon_sym_CARET); + END_STATE(); + case 139: + ACCEPT_TOKEN(anon_sym_TILDE); + END_STATE(); + case 140: + ACCEPT_TOKEN(anon_sym_GT_EQ); + END_STATE(); + case 141: + ACCEPT_TOKEN(anon_sym_GT); + if (lookahead == '=') ADVANCE(140); + END_STATE(); + case 142: + ACCEPT_TOKEN(anon_sym_LT_EQ); + END_STATE(); + case 143: + ACCEPT_TOKEN(anon_sym_LT); + if (lookahead == '=') ADVANCE(142); + END_STATE(); + case 144: + ACCEPT_TOKEN(anon_sym_EQ); + END_STATE(); + case 145: + ACCEPT_TOKEN(anon_sym_EQ); + if (lookahead == '=') ADVANCE(159); + END_STATE(); + case 146: + ACCEPT_TOKEN(sym_version_literal); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(146); + END_STATE(); + case 147: + ACCEPT_TOKEN(anon_sym_LBRACE); + END_STATE(); + case 148: + ACCEPT_TOKEN(anon_sym_RBRACE); + END_STATE(); + case 149: + ACCEPT_TOKEN(anon_sym_LPAREN); + END_STATE(); + case 150: + ACCEPT_TOKEN(anon_sym_COMMA); + END_STATE(); + case 151: + ACCEPT_TOKEN(anon_sym_RPAREN); + END_STATE(); + case 152: + ACCEPT_TOKEN(anon_sym_COLON); + END_STATE(); + case 153: + ACCEPT_TOKEN(anon_sym_DOTpush); + END_STATE(); + case 154: + ACCEPT_TOKEN(anon_sym_console_DOTlog); + END_STATE(); + case 155: + ACCEPT_TOKEN(anon_sym_PIPE_PIPE); + END_STATE(); + case 156: + ACCEPT_TOKEN(anon_sym_AMP_AMP); + END_STATE(); + case 157: + ACCEPT_TOKEN(anon_sym_PIPE); + if (lookahead == '|') ADVANCE(155); + END_STATE(); + case 158: + ACCEPT_TOKEN(anon_sym_AMP); + if (lookahead == '&') ADVANCE(156); + END_STATE(); + case 159: + ACCEPT_TOKEN(anon_sym_EQ_EQ); + END_STATE(); + case 160: + ACCEPT_TOKEN(anon_sym_BANG_EQ); + END_STATE(); + case 161: + ACCEPT_TOKEN(anon_sym_PLUS); + END_STATE(); + case 162: + ACCEPT_TOKEN(anon_sym_DASH); + END_STATE(); + case 163: + ACCEPT_TOKEN(anon_sym_DASH); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(182); + END_STATE(); + case 164: + ACCEPT_TOKEN(anon_sym_STAR); + END_STATE(); + case 165: + ACCEPT_TOKEN(anon_sym_SLASH); + if (lookahead == '*') ADVANCE(10); + if (lookahead == '/') ADVANCE(215); + END_STATE(); + case 166: + ACCEPT_TOKEN(anon_sym_PERCENT); + END_STATE(); + case 167: + ACCEPT_TOKEN(anon_sym_BANG); + END_STATE(); + case 168: + ACCEPT_TOKEN(anon_sym_BANG); + if (lookahead == '=') ADVANCE(160); + END_STATE(); + case 169: + ACCEPT_TOKEN(anon_sym_LBRACK); + END_STATE(); + case 170: + ACCEPT_TOKEN(anon_sym_RBRACK); + END_STATE(); + case 171: + ACCEPT_TOKEN(sym_unary_suffix); + END_STATE(); + case 172: + ACCEPT_TOKEN(anon_sym_DOTsplit); + END_STATE(); + case 173: + ACCEPT_TOKEN(anon_sym_DOTslice); + END_STATE(); + case 174: + ACCEPT_TOKEN(anon_sym_DOTreverse); + END_STATE(); + case 175: + ACCEPT_TOKEN(sym_output_root); + if (lookahead == '.') ADVANCE(76); + END_STATE(); + case 176: + ACCEPT_TOKEN(sym_input_root); + if (lookahead == '.') ADVANCE(75); + END_STATE(); + case 177: + ACCEPT_TOKEN(anon_sym_DOT); + END_STATE(); + case 178: + ACCEPT_TOKEN(anon_sym_DOT); + if (lookahead == 'l') ADVANCE(33); + if (lookahead == 'p') ADVANCE(118); + if (lookahead == 'r') ADVANCE(34); + END_STATE(); + case 179: + ACCEPT_TOKEN(sym_array_bound); + if (lookahead == '_') ADVANCE(130); + if (lookahead == 'E' || + lookahead == 'e') ADVANCE(131); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(179); + END_STATE(); + case 180: + ACCEPT_TOKEN(sym_array_bound); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(180); + END_STATE(); + case 181: + ACCEPT_TOKEN(sym_number); + if (lookahead == '_') ADVANCE(130); + if (lookahead == 'E' || + lookahead == 'e') ADVANCE(131); + if (lookahead == 'X' || + lookahead == 'x') ADVANCE(185); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(182); + END_STATE(); + case 182: + ACCEPT_TOKEN(sym_number); + if (lookahead == '_') ADVANCE(130); + if (lookahead == 'E' || + lookahead == 'e') ADVANCE(131); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(182); + END_STATE(); + case 183: + ACCEPT_TOKEN(sym_number); + if (lookahead == '_') ADVANCE(131); + if (('0' <= lookahead && lookahead <= '9')) ADVANCE(183); + END_STATE(); + case 184: + ACCEPT_TOKEN(sym_string_literal); + END_STATE(); + case 185: + ACCEPT_TOKEN(sym_hex_literal); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'F') || + ('a' <= lookahead && lookahead <= 'f')) ADVANCE(185); + END_STATE(); + case 186: + ACCEPT_TOKEN(anon_sym_this_DOTage); + END_STATE(); + case 187: + ACCEPT_TOKEN(anon_sym_tx_DOTtime); + END_STATE(); + case 188: + ACCEPT_TOKEN(anon_sym_this_DOTactiveInputIndex); + END_STATE(); + case 189: + ACCEPT_TOKEN(anon_sym_this_DOTactiveScriptPubKey); + END_STATE(); + case 190: + ACCEPT_TOKEN(anon_sym_this_DOTscriptSizeDataPrefix); + END_STATE(); + case 191: + ACCEPT_TOKEN(anon_sym_this_DOTscriptSize); + if (lookahead == 'D') ADVANCE(24); + END_STATE(); + case 192: + ACCEPT_TOKEN(anon_sym_tx_DOTinputs_DOTlength); + END_STATE(); + case 193: + ACCEPT_TOKEN(anon_sym_tx_DOToutputs_DOTlength); + END_STATE(); + case 194: + ACCEPT_TOKEN(anon_sym_tx_DOTversion); + END_STATE(); + case 195: + ACCEPT_TOKEN(anon_sym_tx_DOTlocktime); + END_STATE(); + case 196: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == '.') ADVANCE(60); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 197: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == '.') ADVANCE(21); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 198: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == '.') ADVANCE(72); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 199: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == '.') ADVANCE(61); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 200: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == '.') ADVANCE(23); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 201: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'e') ADVANCE(198); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 202: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'h') ADVANCE(204); + if (lookahead == 'x') ADVANCE(196); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 203: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'h') ADVANCE(205); + if (lookahead == 'x') ADVANCE(199); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 204: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'i') ADVANCE(211); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 205: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'i') ADVANCE(212); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 206: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'l') ADVANCE(201); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 207: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'n') ADVANCE(210); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 208: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'o') ADVANCE(207); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 209: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 'o') ADVANCE(206); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 210: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 's') ADVANCE(209); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 211: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 's') ADVANCE(197); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 212: + ACCEPT_TOKEN(sym_identifier); + if (lookahead == 's') ADVANCE(200); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 213: + ACCEPT_TOKEN(sym_identifier); + if (('0' <= lookahead && lookahead <= '9') || + ('A' <= lookahead && lookahead <= 'Z') || + lookahead == '_' || + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(213); + END_STATE(); + case 214: + ACCEPT_TOKEN(sym_comment); + END_STATE(); + case 215: + ACCEPT_TOKEN(sym_comment); + if (lookahead != 0 && + lookahead != '\n') ADVANCE(215); + END_STATE(); + default: + return false; + } +} + +static bool ts_lex_keywords(TSLexer *lexer, TSStateId state) { + START_LEXER(); + eof = lexer->eof(lexer); + switch (state) { + case 0: + ADVANCE_MAP( + 'b', 1, + 'c', 2, + 'd', 3, + 'e', 4, + 'f', 5, + 'g', 6, + 'h', 7, + 'i', 8, + 'k', 9, + 'l', 10, + 'm', 11, + 'n', 12, + 'o', 13, + 'p', 14, + 'r', 15, + 's', 16, + 't', 17, + 'v', 18, + 'w', 19, + 'y', 20, + ); + if (('\t' <= lookahead && lookahead <= '\r') || + lookahead == ' ') SKIP(0); + END_STATE(); + case 1: + if (lookahead == 'o') ADVANCE(21); + if (lookahead == 'y') ADVANCE(22); + END_STATE(); + case 2: + if (lookahead == 'o') ADVANCE(23); + END_STATE(); + case 3: + if (lookahead == 'a') ADVANCE(24); + END_STATE(); + case 4: + if (lookahead == 'l') ADVANCE(25); + if (lookahead == 'n') ADVANCE(26); + END_STATE(); + case 5: + if (lookahead == 'a') ADVANCE(27); + if (lookahead == 'o') ADVANCE(28); + if (lookahead == 'u') ADVANCE(29); + END_STATE(); + case 6: + if (lookahead == 'r') ADVANCE(30); + END_STATE(); + case 7: + if (lookahead == 'o') ADVANCE(31); + END_STATE(); + case 8: + if (lookahead == 'f') ADVANCE(32); + if (lookahead == 'n') ADVANCE(33); + END_STATE(); + case 9: + if (lookahead == 'a') ADVANCE(34); + END_STATE(); + case 10: + if (lookahead == 'i') ADVANCE(35); + END_STATE(); + case 11: + if (lookahead == 'i') ADVANCE(36); + END_STATE(); + case 12: + if (lookahead == 'e') ADVANCE(37); + END_STATE(); + case 13: + if (lookahead == 'u') ADVANCE(38); + END_STATE(); + case 14: + if (lookahead == 'r') ADVANCE(39); + if (lookahead == 'u') ADVANCE(40); + END_STATE(); + case 15: + if (lookahead == 'e') ADVANCE(41); + END_STATE(); + case 16: + if (lookahead == 'c') ADVANCE(42); + if (lookahead == 'e') ADVANCE(43); + if (lookahead == 'i') ADVANCE(44); + if (lookahead == 't') ADVANCE(45); + END_STATE(); + case 17: + if (lookahead == 'r') ADVANCE(46); + END_STATE(); + case 18: + if (lookahead == 'a') ADVANCE(47); + END_STATE(); + case 19: + if (lookahead == 'e') ADVANCE(48); + END_STATE(); + case 20: + if (lookahead == 'i') ADVANCE(49); + END_STATE(); + case 21: + if (lookahead == 'o') ADVANCE(50); + END_STATE(); + case 22: + if (lookahead == 't') ADVANCE(51); + END_STATE(); + case 23: + if (lookahead == 'n') ADVANCE(52); + END_STATE(); + case 24: + if (lookahead == 't') ADVANCE(53); + if (lookahead == 'y') ADVANCE(54); + END_STATE(); + case 25: + if (lookahead == 's') ADVANCE(55); + END_STATE(); + case 26: + if (lookahead == 't') ADVANCE(56); + END_STATE(); + case 27: + if (lookahead == 'l') ADVANCE(57); + END_STATE(); + case 28: + if (lookahead == 'r') ADVANCE(58); + END_STATE(); + case 29: + if (lookahead == 'n') ADVANCE(59); + END_STATE(); + case 30: + if (lookahead == 'a') ADVANCE(60); + END_STATE(); + case 31: + if (lookahead == 'u') ADVANCE(61); + END_STATE(); + case 32: + ACCEPT_TOKEN(anon_sym_if); + END_STATE(); + case 33: + if (lookahead == 't') ADVANCE(62); + END_STATE(); + case 34: + if (lookahead == 's') ADVANCE(63); + END_STATE(); + case 35: + if (lookahead == 't') ADVANCE(64); + END_STATE(); + case 36: + if (lookahead == 'n') ADVANCE(65); + END_STATE(); + case 37: + if (lookahead == 'w') ADVANCE(66); + END_STATE(); + case 38: + if (lookahead == 't') ADVANCE(67); + END_STATE(); + case 39: + if (lookahead == 'a') ADVANCE(68); + END_STATE(); + case 40: + if (lookahead == 'b') ADVANCE(69); + END_STATE(); + case 41: + if (lookahead == 'q') ADVANCE(70); + if (lookahead == 't') ADVANCE(71); + END_STATE(); + case 42: + if (lookahead == 'r') ADVANCE(72); + END_STATE(); + case 43: + if (lookahead == 'c') ADVANCE(73); + END_STATE(); + case 44: + if (lookahead == 'g') ADVANCE(74); + if (lookahead == 'l') ADVANCE(75); + END_STATE(); + case 45: + if (lookahead == 'r') ADVANCE(76); + END_STATE(); + case 46: + if (lookahead == 'u') ADVANCE(77); + END_STATE(); + case 47: + if (lookahead == 'l') ADVANCE(78); + END_STATE(); + case 48: + if (lookahead == 'e') ADVANCE(79); + END_STATE(); + case 49: + if (lookahead == 'e') ADVANCE(80); + END_STATE(); + case 50: + if (lookahead == 'l') ADVANCE(81); + END_STATE(); + case 51: + if (lookahead == 'e') ADVANCE(82); + END_STATE(); + case 52: + if (lookahead == 's') ADVANCE(83); + if (lookahead == 't') ADVANCE(84); + END_STATE(); + case 53: + if (lookahead == 'a') ADVANCE(85); + if (lookahead == 'e') ADVANCE(86); + END_STATE(); + case 54: + if (lookahead == 's') ADVANCE(87); + END_STATE(); + case 55: + if (lookahead == 'e') ADVANCE(88); + END_STATE(); + case 56: + if (lookahead == 'r') ADVANCE(89); + END_STATE(); + case 57: + if (lookahead == 's') ADVANCE(90); + END_STATE(); + case 58: + ACCEPT_TOKEN(anon_sym_for); + END_STATE(); + case 59: + if (lookahead == 'c') ADVANCE(91); + END_STATE(); + case 60: + if (lookahead == 'i') ADVANCE(92); + END_STATE(); + case 61: + if (lookahead == 'r') ADVANCE(93); + END_STATE(); + case 62: + ACCEPT_TOKEN(anon_sym_int); + END_STATE(); + case 63: + ACCEPT_TOKEN(anon_sym_kas); + END_STATE(); + case 64: + if (lookahead == 'r') ADVANCE(94); + END_STATE(); + case 65: + if (lookahead == 'u') ADVANCE(95); + END_STATE(); + case 66: + ACCEPT_TOKEN(anon_sym_new); + END_STATE(); + case 67: + if (lookahead == 'p') ADVANCE(96); + END_STATE(); + case 68: + if (lookahead == 'g') ADVANCE(97); + END_STATE(); + case 69: + if (lookahead == 'k') ADVANCE(98); + END_STATE(); + case 70: + if (lookahead == 'u') ADVANCE(99); + END_STATE(); + case 71: + if (lookahead == 'u') ADVANCE(100); + END_STATE(); + case 72: + if (lookahead == 'i') ADVANCE(101); + END_STATE(); + case 73: + if (lookahead == 'o') ADVANCE(102); + END_STATE(); + case 74: + ACCEPT_TOKEN(anon_sym_sig); + if (lookahead == 'S') ADVANCE(103); + END_STATE(); + case 75: + if (lookahead == 'v') ADVANCE(104); + END_STATE(); + case 76: + if (lookahead == 'i') ADVANCE(105); + END_STATE(); + case 77: + if (lookahead == 'e') ADVANCE(106); + END_STATE(); + case 78: + if (lookahead == 'u') ADVANCE(107); + END_STATE(); + case 79: + if (lookahead == 'k') ADVANCE(108); + END_STATE(); + case 80: + if (lookahead == 'l') ADVANCE(109); + END_STATE(); + case 81: + ACCEPT_TOKEN(anon_sym_bool); + END_STATE(); + case 82: + ACCEPT_TOKEN(anon_sym_byte); + END_STATE(); + case 83: + if (lookahead == 't') ADVANCE(110); + END_STATE(); + case 84: + if (lookahead == 'r') ADVANCE(111); + END_STATE(); + case 85: + if (lookahead == 's') ADVANCE(112); + END_STATE(); + case 86: + ACCEPT_TOKEN(anon_sym_date); + END_STATE(); + case 87: + ACCEPT_TOKEN(anon_sym_days); + END_STATE(); + case 88: + ACCEPT_TOKEN(anon_sym_else); + END_STATE(); + case 89: + if (lookahead == 'y') ADVANCE(113); + END_STATE(); + case 90: + if (lookahead == 'e') ADVANCE(114); + END_STATE(); + case 91: + if (lookahead == 't') ADVANCE(115); + END_STATE(); + case 92: + if (lookahead == 'n') ADVANCE(116); + END_STATE(); + case 93: + if (lookahead == 's') ADVANCE(117); + END_STATE(); + case 94: + if (lookahead == 'a') ADVANCE(118); + END_STATE(); + case 95: + if (lookahead == 't') ADVANCE(119); + END_STATE(); + case 96: + if (lookahead == 'o') ADVANCE(120); + END_STATE(); + case 97: + if (lookahead == 'm') ADVANCE(121); + END_STATE(); + case 98: + if (lookahead == 'e') ADVANCE(122); + END_STATE(); + case 99: + if (lookahead == 'i') ADVANCE(123); + END_STATE(); + case 100: + if (lookahead == 'r') ADVANCE(124); + END_STATE(); + case 101: + if (lookahead == 'p') ADVANCE(125); + END_STATE(); + case 102: + if (lookahead == 'n') ADVANCE(126); + END_STATE(); + case 103: + if (lookahead == 'c') ADVANCE(127); + END_STATE(); + case 104: + if (lookahead == 'e') ADVANCE(128); + END_STATE(); + case 105: + if (lookahead == 'n') ADVANCE(129); + END_STATE(); + case 106: + ACCEPT_TOKEN(anon_sym_true); + END_STATE(); + case 107: + if (lookahead == 'e') ADVANCE(130); + END_STATE(); + case 108: + if (lookahead == 's') ADVANCE(131); + END_STATE(); + case 109: + if (lookahead == 'd') ADVANCE(132); + END_STATE(); + case 110: + if (lookahead == 'a') ADVANCE(133); + END_STATE(); + case 111: + if (lookahead == 'a') ADVANCE(134); + END_STATE(); + case 112: + if (lookahead == 'i') ADVANCE(135); + END_STATE(); + case 113: + if (lookahead == 'p') ADVANCE(136); + END_STATE(); + case 114: + ACCEPT_TOKEN(anon_sym_false); + END_STATE(); + case 115: + if (lookahead == 'i') ADVANCE(137); + END_STATE(); + case 116: + if (lookahead == 's') ADVANCE(138); + END_STATE(); + case 117: + ACCEPT_TOKEN(anon_sym_hours); + END_STATE(); + case 118: + if (lookahead == 's') ADVANCE(139); + END_STATE(); + case 119: + if (lookahead == 'e') ADVANCE(140); + END_STATE(); + case 120: + if (lookahead == 'i') ADVANCE(141); + END_STATE(); + case 121: + if (lookahead == 'a') ADVANCE(142); + END_STATE(); + case 122: + if (lookahead == 'y') ADVANCE(143); + END_STATE(); + case 123: + if (lookahead == 'r') ADVANCE(144); + END_STATE(); + case 124: + if (lookahead == 'n') ADVANCE(145); + END_STATE(); + case 125: + if (lookahead == 't') ADVANCE(146); + END_STATE(); + case 126: + if (lookahead == 'd') ADVANCE(147); + END_STATE(); + case 127: + if (lookahead == 'r') ADVANCE(148); + END_STATE(); + case 128: + if (lookahead == 'r') ADVANCE(149); + END_STATE(); + case 129: + if (lookahead == 'g') ADVANCE(150); + END_STATE(); + case 130: + ACCEPT_TOKEN(anon_sym_value); + END_STATE(); + case 131: + ACCEPT_TOKEN(anon_sym_weeks); + END_STATE(); + case 132: + ACCEPT_TOKEN(anon_sym_yield); + END_STATE(); + case 133: + if (lookahead == 'n') ADVANCE(151); + END_STATE(); + case 134: + if (lookahead == 'c') ADVANCE(152); + END_STATE(); + case 135: + if (lookahead == 'g') ADVANCE(153); + END_STATE(); + case 136: + if (lookahead == 'o') ADVANCE(154); + END_STATE(); + case 137: + if (lookahead == 'o') ADVANCE(155); + END_STATE(); + case 138: + ACCEPT_TOKEN(anon_sym_grains); + END_STATE(); + case 139: + ACCEPT_TOKEN(anon_sym_litras); + END_STATE(); + case 140: + if (lookahead == 's') ADVANCE(156); + END_STATE(); + case 141: + if (lookahead == 'n') ADVANCE(157); + END_STATE(); + case 142: + ACCEPT_TOKEN(anon_sym_pragma); + END_STATE(); + case 143: + ACCEPT_TOKEN(anon_sym_pubkey); + END_STATE(); + case 144: + if (lookahead == 'e') ADVANCE(158); + END_STATE(); + case 145: + ACCEPT_TOKEN(anon_sym_return); + END_STATE(); + case 146: + if (lookahead == 'P') ADVANCE(159); + END_STATE(); + case 147: + if (lookahead == 's') ADVANCE(160); + END_STATE(); + case 148: + if (lookahead == 'i') ADVANCE(161); + END_STATE(); + case 149: + if (lookahead == 's') ADVANCE(162); + END_STATE(); + case 150: + ACCEPT_TOKEN(anon_sym_string); + END_STATE(); + case 151: + if (lookahead == 't') ADVANCE(163); + END_STATE(); + case 152: + if (lookahead == 't') ADVANCE(164); + END_STATE(); + case 153: + ACCEPT_TOKEN(anon_sym_datasig); + END_STATE(); + case 154: + if (lookahead == 'i') ADVANCE(165); + END_STATE(); + case 155: + if (lookahead == 'n') ADVANCE(166); + END_STATE(); + case 156: + ACCEPT_TOKEN(anon_sym_minutes); + END_STATE(); + case 157: + if (lookahead == 't') ADVANCE(167); + END_STATE(); + case 158: + ACCEPT_TOKEN(anon_sym_require); + END_STATE(); + case 159: + if (lookahead == 'u') ADVANCE(168); + END_STATE(); + case 160: + ACCEPT_TOKEN(anon_sym_seconds); + END_STATE(); + case 161: + if (lookahead == 'p') ADVANCE(169); + END_STATE(); + case 162: + if (lookahead == 'c') ADVANCE(170); + END_STATE(); + case 163: + ACCEPT_TOKEN(anon_sym_constant); + END_STATE(); + case 164: + ACCEPT_TOKEN(anon_sym_contract); + END_STATE(); + case 165: + if (lookahead == 'n') ADVANCE(171); + END_STATE(); + case 166: + ACCEPT_TOKEN(anon_sym_function); + END_STATE(); + case 167: + if (lookahead == 'I') ADVANCE(172); + if (lookahead == 'T') ADVANCE(173); + END_STATE(); + case 168: + if (lookahead == 'b') ADVANCE(174); + END_STATE(); + case 169: + if (lookahead == 't') ADVANCE(175); + END_STATE(); + case 170: + if (lookahead == 'r') ADVANCE(176); + END_STATE(); + case 171: + if (lookahead == 't') ADVANCE(177); + END_STATE(); + case 172: + if (lookahead == 'n') ADVANCE(178); + END_STATE(); + case 173: + if (lookahead == 'r') ADVANCE(179); + END_STATE(); + case 174: + if (lookahead == 'K') ADVANCE(180); + END_STATE(); + case 175: + ACCEPT_TOKEN(anon_sym_sigScript); + END_STATE(); + case 176: + if (lookahead == 'i') ADVANCE(181); + END_STATE(); + case 177: + ACCEPT_TOKEN(anon_sym_entrypoint); + END_STATE(); + case 178: + if (lookahead == 'd') ADVANCE(182); + END_STATE(); + case 179: + if (lookahead == 'a') ADVANCE(183); + END_STATE(); + case 180: + if (lookahead == 'e') ADVANCE(184); + END_STATE(); + case 181: + if (lookahead == 'p') ADVANCE(185); + END_STATE(); + case 182: + if (lookahead == 'e') ADVANCE(186); + END_STATE(); + case 183: + if (lookahead == 'n') ADVANCE(187); + END_STATE(); + case 184: + if (lookahead == 'y') ADVANCE(188); + END_STATE(); + case 185: + if (lookahead == 't') ADVANCE(189); + END_STATE(); + case 186: + if (lookahead == 'x') ADVANCE(190); + END_STATE(); + case 187: + if (lookahead == 's') ADVANCE(191); + END_STATE(); + case 188: + ACCEPT_TOKEN(anon_sym_scriptPubKey); + END_STATE(); + case 189: + ACCEPT_TOKEN(anon_sym_silverscript); + END_STATE(); + case 190: + ACCEPT_TOKEN(anon_sym_outpointIndex); + END_STATE(); + case 191: + if (lookahead == 'a') ADVANCE(192); + END_STATE(); + case 192: + if (lookahead == 'c') ADVANCE(193); + END_STATE(); + case 193: + if (lookahead == 't') ADVANCE(194); + END_STATE(); + case 194: + if (lookahead == 'i') ADVANCE(195); + END_STATE(); + case 195: + if (lookahead == 'o') ADVANCE(196); + END_STATE(); + case 196: + if (lookahead == 'n') ADVANCE(197); + END_STATE(); + case 197: + if (lookahead == 'H') ADVANCE(198); + END_STATE(); + case 198: + if (lookahead == 'a') ADVANCE(199); + END_STATE(); + case 199: + if (lookahead == 's') ADVANCE(200); + END_STATE(); + case 200: + if (lookahead == 'h') ADVANCE(201); + END_STATE(); + case 201: + ACCEPT_TOKEN(anon_sym_outpointTransactionHash); + END_STATE(); + default: + return false; + } +} + +static const TSLexerMode ts_lex_modes[STATE_COUNT] = { + [0] = {.lex_state = 0}, + [1] = {.lex_state = 1}, + [2] = {.lex_state = 3}, + [3] = {.lex_state = 2}, + [4] = {.lex_state = 2}, + [5] = {.lex_state = 2}, + [6] = {.lex_state = 2}, + [7] = {.lex_state = 2}, + [8] = {.lex_state = 2}, + [9] = {.lex_state = 2}, + [10] = {.lex_state = 2}, + [11] = {.lex_state = 2}, + [12] = {.lex_state = 2}, + [13] = {.lex_state = 2}, + [14] = {.lex_state = 2}, + [15] = {.lex_state = 2}, + [16] = {.lex_state = 2}, + [17] = {.lex_state = 2}, + [18] = {.lex_state = 2}, + [19] = {.lex_state = 2}, + [20] = {.lex_state = 2}, + [21] = {.lex_state = 2}, + [22] = {.lex_state = 2}, + [23] = {.lex_state = 2}, + [24] = {.lex_state = 2}, + [25] = {.lex_state = 2}, + [26] = {.lex_state = 2}, + [27] = {.lex_state = 2}, + [28] = {.lex_state = 2}, + [29] = {.lex_state = 2}, + [30] = {.lex_state = 2}, + [31] = {.lex_state = 2}, + [32] = {.lex_state = 2}, + [33] = {.lex_state = 2}, + [34] = {.lex_state = 2}, + [35] = {.lex_state = 2}, + [36] = {.lex_state = 2}, + [37] = {.lex_state = 2}, + [38] = {.lex_state = 2}, + [39] = {.lex_state = 2}, + [40] = {.lex_state = 7}, + [41] = {.lex_state = 7}, + [42] = {.lex_state = 7}, + [43] = {.lex_state = 7}, + [44] = {.lex_state = 7}, + [45] = {.lex_state = 7}, + [46] = {.lex_state = 7}, + [47] = {.lex_state = 7}, + [48] = {.lex_state = 7}, + [49] = {.lex_state = 7}, + [50] = {.lex_state = 7}, + [51] = {.lex_state = 7}, + [52] = {.lex_state = 7}, + [53] = {.lex_state = 1}, + [54] = {.lex_state = 7}, + [55] = {.lex_state = 1}, + [56] = {.lex_state = 1}, + [57] = {.lex_state = 1}, + [58] = {.lex_state = 2}, + [59] = {.lex_state = 2}, + [60] = {.lex_state = 1}, + [61] = {.lex_state = 1}, + [62] = {.lex_state = 1}, + [63] = {.lex_state = 1}, + [64] = {.lex_state = 1}, + [65] = {.lex_state = 1}, + [66] = {.lex_state = 1}, + [67] = {.lex_state = 1}, + [68] = {.lex_state = 1}, + [69] = {.lex_state = 1}, + [70] = {.lex_state = 1}, + [71] = {.lex_state = 1}, + [72] = {.lex_state = 1}, + [73] = {.lex_state = 1}, + [74] = {.lex_state = 1}, + [75] = {.lex_state = 1}, + [76] = {.lex_state = 1}, + [77] = {.lex_state = 1}, + [78] = {.lex_state = 1}, + [79] = {.lex_state = 1}, + [80] = {.lex_state = 1}, + [81] = {.lex_state = 1}, + [82] = {.lex_state = 1}, + [83] = {.lex_state = 1}, + [84] = {.lex_state = 1}, + [85] = {.lex_state = 1}, + [86] = {.lex_state = 1}, + [87] = {.lex_state = 1}, + [88] = {.lex_state = 1}, + [89] = {.lex_state = 1}, + [90] = {.lex_state = 1}, + [91] = {.lex_state = 1}, + [92] = {.lex_state = 1}, + [93] = {.lex_state = 1}, + [94] = {.lex_state = 1}, + [95] = {.lex_state = 1}, + [96] = {.lex_state = 1}, + [97] = {.lex_state = 1}, + [98] = {.lex_state = 1}, + [99] = {.lex_state = 1}, + [100] = {.lex_state = 1}, + [101] = {.lex_state = 1}, + [102] = {.lex_state = 1}, + [103] = {.lex_state = 1}, + [104] = {.lex_state = 1}, + [105] = {.lex_state = 1}, + [106] = {.lex_state = 7}, + [107] = {.lex_state = 7}, + [108] = {.lex_state = 1}, + [109] = {.lex_state = 7}, + [110] = {.lex_state = 7}, + [111] = {.lex_state = 7}, + [112] = {.lex_state = 7}, + [113] = {.lex_state = 7}, + [114] = {.lex_state = 7}, + [115] = {.lex_state = 7}, + [116] = {.lex_state = 7}, + [117] = {.lex_state = 7}, + [118] = {.lex_state = 7}, + [119] = {.lex_state = 7}, + [120] = {.lex_state = 7}, + [121] = {.lex_state = 7}, + [122] = {.lex_state = 7}, + [123] = {.lex_state = 7}, + [124] = {.lex_state = 7}, + [125] = {.lex_state = 7}, + [126] = {.lex_state = 7}, + [127] = {.lex_state = 7}, + [128] = {.lex_state = 7}, + [129] = {.lex_state = 7}, + [130] = {.lex_state = 7}, + [131] = {.lex_state = 7}, + [132] = {.lex_state = 7}, + [133] = {.lex_state = 7}, + [134] = {.lex_state = 7}, + [135] = {.lex_state = 1}, + [136] = {.lex_state = 1}, + [137] = {.lex_state = 1}, + [138] = {.lex_state = 1}, + [139] = {.lex_state = 1}, + [140] = {.lex_state = 1}, + [141] = {.lex_state = 1}, + [142] = {.lex_state = 4}, + [143] = {.lex_state = 1}, + [144] = {.lex_state = 4}, + [145] = {.lex_state = 1}, + [146] = {.lex_state = 1}, + [147] = {.lex_state = 4}, + [148] = {.lex_state = 1}, + [149] = {.lex_state = 4}, + [150] = {.lex_state = 1}, + [151] = {.lex_state = 1}, + [152] = {.lex_state = 0}, + [153] = {.lex_state = 0}, + [154] = {.lex_state = 1}, + [155] = {.lex_state = 0}, + [156] = {.lex_state = 1}, + [157] = {.lex_state = 7}, + [158] = {.lex_state = 1}, + [159] = {.lex_state = 7}, + [160] = {.lex_state = 1}, + [161] = {.lex_state = 0}, + [162] = {.lex_state = 1}, + [163] = {.lex_state = 1}, + [164] = {.lex_state = 1}, + [165] = {.lex_state = 0}, + [166] = {.lex_state = 1}, + [167] = {.lex_state = 1}, + [168] = {.lex_state = 1}, + [169] = {.lex_state = 1}, + [170] = {.lex_state = 1}, + [171] = {.lex_state = 0}, + [172] = {.lex_state = 1}, + [173] = {.lex_state = 1}, + [174] = {.lex_state = 1}, + [175] = {.lex_state = 1}, + [176] = {.lex_state = 0}, + [177] = {.lex_state = 1}, + [178] = {.lex_state = 1}, + [179] = {.lex_state = 7}, + [180] = {.lex_state = 7}, + [181] = {.lex_state = 1}, + [182] = {.lex_state = 0}, + [183] = {.lex_state = 1}, + [184] = {.lex_state = 0}, + [185] = {.lex_state = 0}, + [186] = {.lex_state = 0}, + [187] = {.lex_state = 1}, + [188] = {.lex_state = 1}, + [189] = {.lex_state = 0}, + [190] = {.lex_state = 1}, + [191] = {.lex_state = 0}, + [192] = {.lex_state = 0}, + [193] = {.lex_state = 1}, + [194] = {.lex_state = 0}, + [195] = {.lex_state = 0}, + [196] = {.lex_state = 0}, + [197] = {.lex_state = 0}, + [198] = {.lex_state = 0}, + [199] = {.lex_state = 1}, + [200] = {.lex_state = 1}, + [201] = {.lex_state = 1}, + [202] = {.lex_state = 0}, + [203] = {.lex_state = 1}, + [204] = {.lex_state = 3}, + [205] = {.lex_state = 0}, + [206] = {.lex_state = 1}, + [207] = {.lex_state = 1}, + [208] = {.lex_state = 1}, + [209] = {.lex_state = 1}, + [210] = {.lex_state = 1}, + [211] = {.lex_state = 1}, + [212] = {.lex_state = 0}, + [213] = {.lex_state = 3}, + [214] = {.lex_state = 0}, + [215] = {.lex_state = 0}, + [216] = {.lex_state = 1}, + [217] = {.lex_state = 0}, + [218] = {.lex_state = 0}, + [219] = {.lex_state = 0}, + [220] = {.lex_state = 0}, + [221] = {.lex_state = 0}, + [222] = {.lex_state = 1}, + [223] = {.lex_state = 0}, + [224] = {.lex_state = 0}, + [225] = {.lex_state = 0}, + [226] = {.lex_state = 0}, + [227] = {.lex_state = 0}, + [228] = {.lex_state = 1}, + [229] = {.lex_state = 0}, + [230] = {.lex_state = 0}, + [231] = {.lex_state = 0}, + [232] = {.lex_state = 0}, + [233] = {.lex_state = 0}, + [234] = {.lex_state = 3}, + [235] = {.lex_state = 0}, + [236] = {.lex_state = 1}, + [237] = {.lex_state = 0}, + [238] = {.lex_state = 0}, + [239] = {.lex_state = 1}, + [240] = {.lex_state = 0}, + [241] = {.lex_state = 0}, + [242] = {.lex_state = 0}, + [243] = {.lex_state = 0}, + [244] = {.lex_state = 0}, + [245] = {.lex_state = 1}, + [246] = {.lex_state = 0}, + [247] = {.lex_state = 1}, + [248] = {.lex_state = 0}, + [249] = {.lex_state = 0}, + [250] = {.lex_state = 0}, + [251] = {.lex_state = 0}, + [252] = {.lex_state = 0}, + [253] = {.lex_state = 0}, + [254] = {.lex_state = 0}, + [255] = {.lex_state = 1}, + [256] = {.lex_state = 1}, + [257] = {.lex_state = 1}, + [258] = {.lex_state = 1}, + [259] = {.lex_state = 0}, + [260] = {.lex_state = 0}, + [261] = {.lex_state = 0}, + [262] = {.lex_state = 1}, + [263] = {.lex_state = 1}, + [264] = {.lex_state = 1}, + [265] = {.lex_state = 0}, + [266] = {.lex_state = 0}, + [267] = {.lex_state = 0}, + [268] = {.lex_state = 0}, + [269] = {.lex_state = 0}, + [270] = {.lex_state = 0}, + [271] = {.lex_state = 0}, + [272] = {.lex_state = 0}, + [273] = {.lex_state = 0}, + [274] = {.lex_state = 1}, + [275] = {.lex_state = 0}, + [276] = {.lex_state = 1}, + [277] = {.lex_state = 0}, + [278] = {.lex_state = 1}, + [279] = {.lex_state = 0}, + [280] = {.lex_state = 0}, + [281] = {.lex_state = 0}, + [282] = {.lex_state = 0}, + [283] = {.lex_state = 0}, + [284] = {.lex_state = 1}, + [285] = {.lex_state = 0}, + [286] = {.lex_state = 0}, + [287] = {.lex_state = 3}, + [288] = {.lex_state = 2}, + [289] = {.lex_state = 2}, + [290] = {.lex_state = 0}, + [291] = {.lex_state = 0}, + [292] = {.lex_state = 0}, + [293] = {.lex_state = 7}, + [294] = {.lex_state = 1}, + [295] = {.lex_state = 0}, + [296] = {.lex_state = 0}, + [297] = {.lex_state = 1}, + [298] = {.lex_state = 0}, + [299] = {.lex_state = 1}, + [300] = {.lex_state = 0}, + [301] = {.lex_state = 0}, + [302] = {.lex_state = 0}, + [303] = {.lex_state = 0}, + [304] = {.lex_state = 0}, + [305] = {.lex_state = 7}, + [306] = {.lex_state = 0}, + [307] = {.lex_state = 0}, + [308] = {.lex_state = 0}, + [309] = {.lex_state = 1}, + [310] = {.lex_state = 0}, + [311] = {.lex_state = 1}, + [312] = {.lex_state = 3}, + [313] = {.lex_state = 2}, + [314] = {.lex_state = 0}, + [315] = {.lex_state = 0}, + [316] = {.lex_state = 0}, + [317] = {.lex_state = 3}, + [318] = {.lex_state = 3}, + [319] = {.lex_state = 1}, + [320] = {.lex_state = 0}, + [321] = {.lex_state = 0}, + [322] = {.lex_state = 3}, + [323] = {.lex_state = 0}, + [324] = {.lex_state = 0}, + [325] = {.lex_state = 0}, + [326] = {.lex_state = 3}, + [327] = {.lex_state = 0}, + [328] = {.lex_state = 0}, + [329] = {.lex_state = 0}, + [330] = {.lex_state = 0}, + [331] = {.lex_state = 0}, + [332] = {.lex_state = 0}, + [333] = {.lex_state = 0}, + [334] = {.lex_state = 0}, + [335] = {.lex_state = 0}, + [336] = {.lex_state = 0}, + [337] = {.lex_state = 0}, + [338] = {.lex_state = 3}, + [339] = {.lex_state = 0}, + [340] = {.lex_state = 0}, + [341] = {.lex_state = 0}, + [342] = {.lex_state = 0}, + [343] = {.lex_state = 0}, + [344] = {.lex_state = 0}, + [345] = {.lex_state = 0}, + [346] = {.lex_state = 0}, + [347] = {.lex_state = 0}, + [348] = {.lex_state = 1}, + [349] = {.lex_state = 0}, + [350] = {.lex_state = 1}, + [351] = {.lex_state = 3}, + [352] = {.lex_state = 0}, + [353] = {.lex_state = 0}, + [354] = {.lex_state = 0}, + [355] = {.lex_state = 0}, + [356] = {.lex_state = 0}, + [357] = {.lex_state = 0}, + [358] = {.lex_state = 0}, + [359] = {.lex_state = 0}, + [360] = {.lex_state = 0}, + [361] = {.lex_state = 3}, + [362] = {.lex_state = 1}, + [363] = {.lex_state = 0}, + [364] = {.lex_state = 0}, + [365] = {.lex_state = 0}, + [366] = {.lex_state = 0}, + [367] = {.lex_state = 0}, + [368] = {.lex_state = 0}, + [369] = {.lex_state = 1}, + [370] = {.lex_state = 0}, + [371] = {.lex_state = 0}, + [372] = {.lex_state = 0}, + [373] = {.lex_state = 3}, + [374] = {.lex_state = 0}, + [375] = {.lex_state = 0}, + [376] = {.lex_state = 0}, + [377] = {.lex_state = 0}, + [378] = {.lex_state = 1}, + [379] = {.lex_state = 0}, + [380] = {.lex_state = 0}, + [381] = {.lex_state = 0}, + [382] = {.lex_state = 0}, + [383] = {.lex_state = 1}, + [384] = {.lex_state = 0}, + [385] = {.lex_state = 0}, + [386] = {.lex_state = 0}, + [387] = {.lex_state = 0}, + [388] = {.lex_state = 0}, +}; + +static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { + [STATE(0)] = { + [ts_builtin_sym_end] = ACTIONS(1), + [sym_identifier] = ACTIONS(1), + [anon_sym_pragma] = ACTIONS(1), + [anon_sym_silverscript] = ACTIONS(1), + [anon_sym_SEMI] = ACTIONS(1), + [anon_sym_CARET] = ACTIONS(1), + [anon_sym_TILDE] = ACTIONS(1), + [anon_sym_GT_EQ] = ACTIONS(1), + [anon_sym_GT] = ACTIONS(1), + [anon_sym_LT_EQ] = ACTIONS(1), + [anon_sym_LT] = ACTIONS(1), + [anon_sym_EQ] = ACTIONS(1), + [anon_sym_contract] = ACTIONS(1), + [anon_sym_LBRACE] = ACTIONS(1), + [anon_sym_RBRACE] = ACTIONS(1), + [anon_sym_entrypoint] = ACTIONS(1), + [anon_sym_function] = ACTIONS(1), + [anon_sym_constant] = ACTIONS(1), + [anon_sym_LPAREN] = ACTIONS(1), + [anon_sym_COMMA] = ACTIONS(1), + [anon_sym_RPAREN] = ACTIONS(1), + [anon_sym_COLON] = ACTIONS(1), + [anon_sym_DOTpush] = ACTIONS(1), + [anon_sym_return] = ACTIONS(1), + [anon_sym_require] = ACTIONS(1), + [anon_sym_if] = ACTIONS(1), + [anon_sym_else] = ACTIONS(1), + [anon_sym_for] = ACTIONS(1), + [anon_sym_yield] = ACTIONS(1), + [anon_sym_console_DOTlog] = ACTIONS(1), + [anon_sym_PIPE_PIPE] = ACTIONS(1), + [anon_sym_AMP_AMP] = ACTIONS(1), + [anon_sym_PIPE] = ACTIONS(1), + [anon_sym_AMP] = ACTIONS(1), + [anon_sym_EQ_EQ] = ACTIONS(1), + [anon_sym_BANG_EQ] = ACTIONS(1), + [anon_sym_PLUS] = ACTIONS(1), + [anon_sym_DASH] = ACTIONS(1), + [anon_sym_STAR] = ACTIONS(1), + [anon_sym_SLASH] = ACTIONS(1), + [anon_sym_PERCENT] = ACTIONS(1), + [anon_sym_BANG] = ACTIONS(1), + [anon_sym_LBRACK] = ACTIONS(1), + [anon_sym_RBRACK] = ACTIONS(1), + [sym_unary_suffix] = ACTIONS(1), + [anon_sym_DOTreverse] = ACTIONS(1), + [anon_sym_new] = ACTIONS(1), + [sym_output_root] = ACTIONS(1), + [sym_input_root] = ACTIONS(1), + [anon_sym_DOT] = ACTIONS(1), + [anon_sym_value] = ACTIONS(1), + [anon_sym_scriptPubKey] = ACTIONS(1), + [anon_sym_outpointTransactionHash] = ACTIONS(1), + [anon_sym_outpointIndex] = ACTIONS(1), + [anon_sym_sigScript] = ACTIONS(1), + [anon_sym_int] = ACTIONS(1), + [anon_sym_bool] = ACTIONS(1), + [anon_sym_string] = ACTIONS(1), + [anon_sym_pubkey] = ACTIONS(1), + [anon_sym_sig] = ACTIONS(1), + [anon_sym_datasig] = ACTIONS(1), + [anon_sym_byte] = ACTIONS(1), + [sym_array_bound] = ACTIONS(1), + [anon_sym_true] = ACTIONS(1), + [anon_sym_false] = ACTIONS(1), + [anon_sym_litras] = ACTIONS(1), + [anon_sym_grains] = ACTIONS(1), + [anon_sym_kas] = ACTIONS(1), + [anon_sym_seconds] = ACTIONS(1), + [anon_sym_minutes] = ACTIONS(1), + [anon_sym_hours] = ACTIONS(1), + [anon_sym_days] = ACTIONS(1), + [anon_sym_weeks] = ACTIONS(1), + [sym_number] = ACTIONS(1), + [sym_string_literal] = ACTIONS(1), + [anon_sym_date] = ACTIONS(1), + [sym_hex_literal] = ACTIONS(1), + [anon_sym_this_DOTage] = ACTIONS(1), + [anon_sym_tx_DOTtime] = ACTIONS(1), + [anon_sym_this_DOTactiveInputIndex] = ACTIONS(1), + [anon_sym_this_DOTactiveScriptPubKey] = ACTIONS(1), + [anon_sym_this_DOTscriptSizeDataPrefix] = ACTIONS(1), + [anon_sym_this_DOTscriptSize] = ACTIONS(1), + [anon_sym_tx_DOTinputs_DOTlength] = ACTIONS(1), + [anon_sym_tx_DOToutputs_DOTlength] = ACTIONS(1), + [anon_sym_tx_DOTversion] = ACTIONS(1), + [anon_sym_tx_DOTlocktime] = ACTIONS(1), + [sym_comment] = ACTIONS(3), + }, + [STATE(1)] = { + [sym_source_file] = STATE(306), + [sym_pragma_directive] = STATE(206), + [sym_contract_definition] = STATE(374), + [aux_sym_source_file_repeat1] = STATE(206), + [anon_sym_pragma] = ACTIONS(5), + [anon_sym_contract] = ACTIONS(7), + [sym_comment] = ACTIONS(3), + }, +}; + +static const uint16_t ts_small_parse_table[] = { + [0] = 37, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(253), 1, + sym_expression, + STATE(301), 1, + sym_tx_var, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + ACTIONS(37), 2, + anon_sym_this_DOTage, + anon_sym_tx_DOTtime, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [138] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(43), 1, + anon_sym_RPAREN, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(240), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [272] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(45), 1, + anon_sym_RBRACK, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(243), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [406] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(47), 1, + anon_sym_RBRACK, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(224), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [540] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(49), 1, + anon_sym_RBRACK, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(224), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [674] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(51), 1, + anon_sym_RPAREN, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(224), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [808] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(53), 1, + anon_sym_RPAREN, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(259), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [942] = 36, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + ACTIONS(55), 1, + anon_sym_RPAREN, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(224), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1076] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(303), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1207] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(248), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1338] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(358), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1469] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(365), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1600] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(265), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1731] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(327), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1862] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(333), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [1993] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(335), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2124] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(295), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2255] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(296), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2386] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(291), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2517] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(331), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2648] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(339), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2779] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(224), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [2910] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(355), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3041] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(343), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3172] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(371), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3303] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(376), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3434] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(382), 1, + sym_type_name, + STATE(386), 1, + sym_expression, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3565] = 35, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(197), 1, + sym_logical_and, + STATE(205), 1, + sym_logical_or, + STATE(377), 1, + sym_expression, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3696] = 33, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(189), 1, + sym_bit_or, + STATE(193), 1, + sym_base_type, + STATE(202), 1, + sym_logical_and, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3821] = 32, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(182), 1, + sym_bit_xor, + STATE(193), 1, + sym_base_type, + STATE(196), 1, + sym_bit_or, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [3943] = 31, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(171), 1, + sym_bit_and, + STATE(192), 1, + sym_bit_xor, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4062] = 30, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(152), 1, + sym_equality, + STATE(186), 1, + sym_bit_and, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4178] = 29, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(143), 1, + sym_comparison, + STATE(165), 1, + sym_equality, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4291] = 28, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(140), 1, + sym_term, + STATE(148), 1, + sym_comparison, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4401] = 27, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(103), 1, + sym_factor, + STATE(141), 1, + sym_term, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4508] = 26, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(99), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(108), 1, + sym_factor, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4612] = 25, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(100), 1, + sym_unary, + STATE(102), 1, + sym_postfix, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(39), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4713] = 24, + ACTIONS(3), 1, + sym_comment, + ACTIONS(9), 1, + sym_identifier, + ACTIONS(11), 1, + anon_sym_LBRACE, + ACTIONS(13), 1, + anon_sym_LPAREN, + ACTIONS(15), 1, + anon_sym_DASH, + ACTIONS(17), 1, + anon_sym_BANG, + ACTIONS(19), 1, + anon_sym_LBRACK, + ACTIONS(21), 1, + anon_sym_new, + ACTIONS(23), 1, + sym_output_root, + ACTIONS(25), 1, + sym_input_root, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(41), 1, + anon_sym_this_DOTscriptSize, + STATE(56), 1, + sym_primary, + STATE(101), 1, + sym_postfix, + STATE(193), 1, + sym_base_type, + STATE(382), 1, + sym_type_name, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(58), 2, + sym_unary_op, + aux_sym_unary_repeat1, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + ACTIONS(39), 7, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + STATE(62), 9, + sym_parenthesized, + sym_cast, + sym_function_call, + sym_instantiation, + sym_state_object, + sym_introspection, + sym_array, + sym_literal, + sym_nullary_op, + [4811] = 18, + ACTIONS(3), 1, + sym_comment, + ACTIONS(57), 1, + sym_identifier, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(61), 1, + anon_sym_RBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(227), 1, + sym_state_typed_binding, + STATE(357), 1, + sym_function_call, + STATE(41), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [4886] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(79), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(47), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [4958] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(81), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(47), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5030] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(83), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(42), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5102] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(85), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(47), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5174] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(85), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(48), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5246] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(87), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(44), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5318] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(89), 1, + sym_identifier, + ACTIONS(92), 1, + anon_sym_LBRACE, + ACTIONS(95), 1, + anon_sym_RBRACE, + ACTIONS(97), 1, + anon_sym_LPAREN, + ACTIONS(100), 1, + anon_sym_return, + ACTIONS(103), 1, + anon_sym_require, + ACTIONS(106), 1, + anon_sym_if, + ACTIONS(109), 1, + anon_sym_for, + ACTIONS(112), 1, + anon_sym_yield, + ACTIONS(115), 1, + anon_sym_console_DOTlog, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(47), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(118), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5390] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(121), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(47), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5462] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(123), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(47), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5534] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(59), 1, + anon_sym_LBRACE, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(81), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + STATE(49), 2, + sym_statement, + aux_sym_function_definition_repeat1, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5606] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(125), 1, + anon_sym_LBRACE, + STATE(118), 1, + sym_statement, + STATE(130), 1, + sym_block, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5677] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(125), 1, + anon_sym_LBRACE, + STATE(116), 1, + sym_block, + STATE(118), 1, + sym_statement, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5748] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(91), 1, + sym_number_unit, + ACTIONS(129), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(131), 8, + anon_sym_litras, + anon_sym_grains, + anon_sym_kas, + anon_sym_seconds, + anon_sym_minutes, + anon_sym_hours, + anon_sym_days, + anon_sym_weeks, + ACTIONS(127), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [5795] = 17, + ACTIONS(3), 1, + sym_comment, + ACTIONS(63), 1, + anon_sym_LPAREN, + ACTIONS(65), 1, + anon_sym_return, + ACTIONS(67), 1, + anon_sym_require, + ACTIONS(69), 1, + anon_sym_if, + ACTIONS(71), 1, + anon_sym_for, + ACTIONS(73), 1, + anon_sym_yield, + ACTIONS(75), 1, + anon_sym_console_DOTlog, + ACTIONS(77), 1, + sym_identifier, + ACTIONS(125), 1, + anon_sym_LBRACE, + STATE(117), 1, + sym_block, + STATE(118), 1, + sym_statement, + STATE(193), 1, + sym_base_type, + STATE(208), 1, + sym_type_name, + STATE(357), 1, + sym_function_call, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + STATE(123), 14, + sym_variable_definition, + sym_tuple_assignment, + sym_push_statement, + sym_function_call_assignment, + sym_state_function_call_assignment, + sym_call_statement, + sym_return_statement, + sym_assign_statement, + sym_time_op_statement, + sym_require_statement, + sym_if_statement, + sym_for_statement, + sym_yield_statement, + sym_console_statement, + [5866] = 10, + ACTIONS(3), 1, + sym_comment, + ACTIONS(137), 1, + anon_sym_LBRACK, + ACTIONS(139), 1, + sym_unary_suffix, + ACTIONS(141), 1, + anon_sym_DOTsplit, + ACTIONS(143), 1, + anon_sym_DOTslice, + ACTIONS(145), 1, + anon_sym_DOTreverse, + STATE(57), 2, + sym_postfix_op, + aux_sym_postfix_repeat1, + STATE(78), 4, + sym_tuple_index, + sym_split_call, + sym_slice_call, + sym_reverse_call, + ACTIONS(135), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(133), 16, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_RBRACK, + [5920] = 10, + ACTIONS(3), 1, + sym_comment, + ACTIONS(137), 1, + anon_sym_LBRACK, + ACTIONS(139), 1, + sym_unary_suffix, + ACTIONS(141), 1, + anon_sym_DOTsplit, + ACTIONS(143), 1, + anon_sym_DOTslice, + ACTIONS(145), 1, + anon_sym_DOTreverse, + STATE(55), 2, + sym_postfix_op, + aux_sym_postfix_repeat1, + STATE(78), 4, + sym_tuple_index, + sym_split_call, + sym_slice_call, + sym_reverse_call, + ACTIONS(149), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(147), 16, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_RBRACK, + [5974] = 10, + ACTIONS(3), 1, + sym_comment, + ACTIONS(155), 1, + anon_sym_LBRACK, + ACTIONS(158), 1, + sym_unary_suffix, + ACTIONS(161), 1, + anon_sym_DOTsplit, + ACTIONS(164), 1, + anon_sym_DOTslice, + ACTIONS(167), 1, + anon_sym_DOTreverse, + STATE(57), 2, + sym_postfix_op, + aux_sym_postfix_repeat1, + STATE(78), 4, + sym_tuple_index, + sym_split_call, + sym_slice_call, + sym_reverse_call, + ACTIONS(153), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(151), 16, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_RBRACK, + [6028] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(174), 1, + anon_sym_DASH, + ACTIONS(177), 1, + anon_sym_BANG, + STATE(58), 2, + sym_unary_op, + aux_sym_unary_repeat1, + ACTIONS(170), 5, + sym_output_root, + sym_input_root, + sym_number, + anon_sym_this_DOTscriptSize, + sym_identifier, + ACTIONS(172), 23, + anon_sym_LBRACE, + anon_sym_LPAREN, + anon_sym_LBRACK, + anon_sym_new, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + anon_sym_true, + anon_sym_false, + sym_string_literal, + anon_sym_date, + sym_hex_literal, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + [6074] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(180), 6, + anon_sym_DASH, + sym_output_root, + sym_input_root, + sym_number, + anon_sym_this_DOTscriptSize, + sym_identifier, + ACTIONS(182), 24, + anon_sym_LBRACE, + anon_sym_LPAREN, + anon_sym_BANG, + anon_sym_LBRACK, + anon_sym_new, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + anon_sym_true, + anon_sym_false, + sym_string_literal, + anon_sym_date, + sym_hex_literal, + anon_sym_this_DOTactiveInputIndex, + anon_sym_this_DOTactiveScriptPubKey, + anon_sym_this_DOTscriptSizeDataPrefix, + anon_sym_tx_DOTinputs_DOTlength, + anon_sym_tx_DOToutputs_DOTlength, + anon_sym_tx_DOTversion, + anon_sym_tx_DOTlocktime, + [6112] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + STATE(92), 1, + sym_expression_list, + ACTIONS(186), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(184), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6152] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(192), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(190), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6186] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(186), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(184), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6220] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(196), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(194), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6254] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(200), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(198), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6288] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(204), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(202), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6322] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(208), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(206), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6356] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(212), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(210), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6390] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(216), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(214), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6424] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(220), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(218), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6458] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(224), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(222), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6492] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(228), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(226), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6526] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(232), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(230), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6560] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(236), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(234), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6594] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(240), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(238), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6628] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(244), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(242), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6662] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(248), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(246), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6696] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(252), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(250), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6730] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(256), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(254), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6764] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(260), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(258), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6798] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(264), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(262), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6832] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(268), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(266), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6866] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(272), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(270), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6900] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(276), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(274), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6934] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(280), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(278), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [6968] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(284), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(282), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7002] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(288), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(286), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7036] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(292), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(290), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7070] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(296), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(294), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7104] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(300), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(298), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7138] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(304), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(302), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7172] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(308), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(306), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7206] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(312), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(310), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7240] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(316), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(314), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7274] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(320), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(318), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7308] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(324), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(322), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7342] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(328), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(326), 21, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_LBRACK, + anon_sym_RBRACK, + sym_unary_suffix, + anon_sym_DOTsplit, + anon_sym_DOTslice, + anon_sym_DOTreverse, + [7376] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(336), 1, + anon_sym_SLASH, + STATE(98), 1, + aux_sym_factor_repeat1, + ACTIONS(334), 2, + anon_sym_STAR, + anon_sym_PERCENT, + ACTIONS(332), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(330), 14, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_RBRACK, + [7412] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(345), 1, + anon_sym_SLASH, + STATE(98), 1, + aux_sym_factor_repeat1, + ACTIONS(342), 2, + anon_sym_STAR, + anon_sym_PERCENT, + ACTIONS(340), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(338), 14, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_RBRACK, + [7448] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(336), 1, + anon_sym_SLASH, + STATE(97), 1, + aux_sym_factor_repeat1, + ACTIONS(334), 2, + anon_sym_STAR, + anon_sym_PERCENT, + ACTIONS(350), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(348), 14, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_RBRACK, + [7484] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(340), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(338), 16, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_RBRACK, + [7513] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(354), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(352), 16, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_RBRACK, + [7542] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(358), 5, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + anon_sym_SLASH, + ACTIONS(356), 16, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_STAR, + anon_sym_PERCENT, + anon_sym_RBRACK, + [7571] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(104), 1, + aux_sym_term_repeat1, + ACTIONS(364), 2, + anon_sym_PLUS, + anon_sym_DASH, + ACTIONS(362), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(360), 12, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [7602] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(105), 1, + aux_sym_term_repeat1, + ACTIONS(364), 2, + anon_sym_PLUS, + anon_sym_DASH, + ACTIONS(368), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(366), 12, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [7633] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(105), 1, + aux_sym_term_repeat1, + ACTIONS(374), 2, + anon_sym_PLUS, + anon_sym_DASH, + ACTIONS(372), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(370), 12, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [7664] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(377), 1, + sym_identifier, + ACTIONS(379), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7690] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(381), 1, + sym_identifier, + ACTIONS(383), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7716] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(372), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(370), 14, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_PLUS, + anon_sym_DASH, + anon_sym_RBRACK, + [7742] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(385), 1, + sym_identifier, + ACTIONS(387), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7768] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(389), 1, + sym_identifier, + ACTIONS(391), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7794] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(393), 1, + sym_identifier, + ACTIONS(395), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7820] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(397), 1, + sym_identifier, + ACTIONS(399), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7846] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(401), 1, + sym_identifier, + ACTIONS(403), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7872] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(405), 1, + sym_identifier, + ACTIONS(407), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7898] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(409), 1, + sym_identifier, + ACTIONS(411), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7924] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(413), 1, + sym_identifier, + ACTIONS(415), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7950] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(417), 1, + sym_identifier, + ACTIONS(421), 1, + anon_sym_else, + ACTIONS(419), 16, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [7978] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(423), 1, + sym_identifier, + ACTIONS(425), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8004] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(427), 1, + sym_identifier, + ACTIONS(429), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8030] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(431), 1, + sym_identifier, + ACTIONS(433), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8056] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(435), 1, + sym_identifier, + ACTIONS(437), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8082] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(439), 1, + sym_identifier, + ACTIONS(441), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8108] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(443), 1, + sym_identifier, + ACTIONS(445), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8134] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(447), 1, + sym_identifier, + ACTIONS(449), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8160] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(451), 1, + sym_identifier, + ACTIONS(453), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8186] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(455), 1, + sym_identifier, + ACTIONS(457), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8212] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(459), 1, + sym_identifier, + ACTIONS(461), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8238] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(463), 1, + sym_identifier, + ACTIONS(465), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8264] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(467), 1, + sym_identifier, + ACTIONS(469), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8290] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(471), 1, + sym_identifier, + ACTIONS(473), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8316] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(475), 1, + sym_identifier, + ACTIONS(477), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8342] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(479), 1, + sym_identifier, + ACTIONS(481), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8368] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(483), 1, + sym_identifier, + ACTIONS(485), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8394] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(487), 1, + sym_identifier, + ACTIONS(489), 17, + anon_sym_LBRACE, + anon_sym_RBRACE, + anon_sym_LPAREN, + anon_sym_return, + anon_sym_require, + anon_sym_if, + anon_sym_else, + anon_sym_for, + anon_sym_yield, + anon_sym_console_DOTlog, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8420] = 6, + ACTIONS(3), 1, + sym_comment, + STATE(135), 1, + aux_sym_comparison_repeat1, + ACTIONS(493), 2, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + ACTIONS(496), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(499), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(491), 10, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [8451] = 9, + ACTIONS(3), 1, + sym_comment, + ACTIONS(501), 1, + anon_sym_RBRACE, + ACTIONS(503), 1, + anon_sym_entrypoint, + ACTIONS(505), 1, + anon_sym_function, + STATE(193), 1, + sym_base_type, + STATE(257), 1, + sym_type_name, + STATE(137), 2, + sym_contract_item, + aux_sym_contract_definition_repeat1, + STATE(177), 3, + sym_function_definition, + sym_constant_definition, + sym_contract_field_definition, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8488] = 9, + ACTIONS(3), 1, + sym_comment, + ACTIONS(503), 1, + anon_sym_entrypoint, + ACTIONS(505), 1, + anon_sym_function, + ACTIONS(507), 1, + anon_sym_RBRACE, + STATE(193), 1, + sym_base_type, + STATE(257), 1, + sym_type_name, + STATE(138), 2, + sym_contract_item, + aux_sym_contract_definition_repeat1, + STATE(177), 3, + sym_function_definition, + sym_constant_definition, + sym_contract_field_definition, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8525] = 9, + ACTIONS(3), 1, + sym_comment, + ACTIONS(509), 1, + anon_sym_RBRACE, + ACTIONS(511), 1, + anon_sym_entrypoint, + ACTIONS(514), 1, + anon_sym_function, + STATE(193), 1, + sym_base_type, + STATE(257), 1, + sym_type_name, + STATE(138), 2, + sym_contract_item, + aux_sym_contract_definition_repeat1, + STATE(177), 3, + sym_function_definition, + sym_constant_definition, + sym_contract_field_definition, + ACTIONS(517), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8562] = 6, + ACTIONS(3), 1, + sym_comment, + STATE(135), 1, + aux_sym_comparison_repeat1, + ACTIONS(522), 2, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + ACTIONS(524), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(526), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(520), 10, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [8593] = 6, + ACTIONS(3), 1, + sym_comment, + STATE(139), 1, + aux_sym_comparison_repeat1, + ACTIONS(522), 2, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + ACTIONS(524), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(530), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(528), 10, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [8624] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(499), 4, + anon_sym_GT, + anon_sym_LT, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(491), 12, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [8648] = 10, + ACTIONS(3), 1, + sym_comment, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(532), 1, + sym_identifier, + ACTIONS(534), 1, + anon_sym_RPAREN, + STATE(268), 1, + sym_console_parameter, + STATE(273), 1, + sym_literal, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + [8683] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(145), 1, + aux_sym_equality_repeat1, + ACTIONS(538), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(540), 2, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + ACTIONS(536), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [8708] = 10, + ACTIONS(3), 1, + sym_comment, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(532), 1, + sym_identifier, + ACTIONS(542), 1, + anon_sym_RPAREN, + STATE(220), 1, + sym_console_parameter, + STATE(273), 1, + sym_literal, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + [8743] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(146), 1, + aux_sym_equality_repeat1, + ACTIONS(540), 2, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + ACTIONS(546), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(544), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [8768] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(146), 1, + aux_sym_equality_repeat1, + ACTIONS(550), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(552), 2, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + ACTIONS(548), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [8793] = 10, + ACTIONS(3), 1, + sym_comment, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(532), 1, + sym_identifier, + ACTIONS(555), 1, + anon_sym_RPAREN, + STATE(268), 1, + sym_console_parameter, + STATE(273), 1, + sym_literal, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + [8828] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(550), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(548), 10, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_EQ_EQ, + anon_sym_BANG_EQ, + anon_sym_RBRACK, + [8848] = 9, + ACTIONS(3), 1, + sym_comment, + ACTIONS(31), 1, + sym_number, + ACTIONS(35), 1, + anon_sym_date, + ACTIONS(532), 1, + sym_identifier, + STATE(268), 1, + sym_console_parameter, + STATE(273), 1, + sym_literal, + ACTIONS(29), 2, + anon_sym_true, + anon_sym_false, + ACTIONS(33), 2, + sym_string_literal, + sym_hex_literal, + STATE(61), 3, + sym_boolean_literal, + sym_number_literal, + sym_date_literal, + [8880] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(557), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(266), 1, + sym_typed_binding, + STATE(378), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8905] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(559), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(270), 1, + sym_parameter, + STATE(383), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [8930] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(563), 1, + anon_sym_PIPE, + ACTIONS(565), 1, + anon_sym_AMP, + STATE(155), 1, + aux_sym_bit_and_repeat1, + ACTIONS(561), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [8953] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(569), 1, + anon_sym_PIPE, + ACTIONS(571), 1, + anon_sym_AMP, + STATE(153), 1, + aux_sym_bit_and_repeat1, + ACTIONS(567), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [8976] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(574), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(270), 1, + sym_parameter, + STATE(383), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9001] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(565), 1, + anon_sym_AMP, + ACTIONS(578), 1, + anon_sym_PIPE, + STATE(153), 1, + aux_sym_bit_and_repeat1, + ACTIONS(576), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9024] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(580), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(244), 1, + sym_parameter, + STATE(383), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9049] = 7, + ACTIONS(3), 1, + sym_comment, + ACTIONS(582), 1, + anon_sym_SEMI, + ACTIONS(588), 1, + sym_version_literal, + STATE(293), 1, + sym_version_operator, + STATE(381), 1, + sym_version_constraint, + ACTIONS(586), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(584), 5, + anon_sym_CARET, + anon_sym_TILDE, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_EQ, + [9076] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(590), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(266), 1, + sym_typed_binding, + STATE(378), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9101] = 7, + ACTIONS(3), 1, + sym_comment, + ACTIONS(588), 1, + sym_version_literal, + STATE(157), 1, + sym_version_constraint, + STATE(293), 1, + sym_version_operator, + STATE(328), 1, + sym_pragma_value, + ACTIONS(586), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(584), 5, + anon_sym_CARET, + anon_sym_TILDE, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_EQ, + [9128] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(592), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9144] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(596), 1, + anon_sym_CARET, + ACTIONS(598), 1, + anon_sym_PIPE, + STATE(176), 1, + aux_sym_bit_xor_repeat1, + ACTIONS(594), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9166] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(193), 1, + sym_base_type, + STATE(230), 1, + sym_typed_binding, + STATE(378), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9188] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(193), 1, + sym_base_type, + STATE(266), 1, + sym_typed_binding, + STATE(378), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9210] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(600), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9226] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(569), 2, + anon_sym_PIPE, + anon_sym_AMP, + ACTIONS(567), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9244] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(602), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(252), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9266] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(604), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9282] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(606), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9298] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(608), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9314] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(610), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9330] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(596), 1, + anon_sym_CARET, + ACTIONS(614), 1, + anon_sym_PIPE, + STATE(161), 1, + aux_sym_bit_xor_repeat1, + ACTIONS(612), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9352] = 5, + ACTIONS(3), 1, + sym_comment, + STATE(193), 1, + sym_base_type, + STATE(270), 1, + sym_parameter, + STATE(383), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9374] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(616), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9390] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(618), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(235), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9412] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(620), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9428] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(624), 1, + anon_sym_CARET, + ACTIONS(627), 1, + anon_sym_PIPE, + STATE(176), 1, + aux_sym_bit_xor_repeat1, + ACTIONS(622), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9450] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(629), 10, + anon_sym_RBRACE, + anon_sym_entrypoint, + anon_sym_function, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9466] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(631), 1, + anon_sym_RPAREN, + STATE(193), 1, + sym_base_type, + STATE(252), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9488] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(635), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(633), 7, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_TILDE, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_EQ, + sym_version_literal, + [9505] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(639), 2, + anon_sym_GT, + anon_sym_LT, + ACTIONS(637), 7, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_TILDE, + anon_sym_GT_EQ, + anon_sym_LT_EQ, + anon_sym_EQ, + sym_version_literal, + [9522] = 4, + ACTIONS(3), 1, + sym_comment, + STATE(193), 1, + sym_base_type, + STATE(252), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9541] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(643), 1, + anon_sym_PIPE, + STATE(184), 1, + aux_sym_bit_or_repeat1, + ACTIONS(641), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9560] = 4, + ACTIONS(3), 1, + sym_comment, + STATE(193), 1, + sym_base_type, + STATE(348), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9579] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(643), 1, + anon_sym_PIPE, + STATE(185), 1, + aux_sym_bit_or_repeat1, + ACTIONS(645), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9598] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(649), 1, + anon_sym_PIPE, + STATE(185), 1, + aux_sym_bit_or_repeat1, + ACTIONS(647), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9617] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(627), 1, + anon_sym_PIPE, + ACTIONS(622), 8, + anon_sym_SEMI, + anon_sym_CARET, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9634] = 4, + ACTIONS(3), 1, + sym_comment, + STATE(193), 1, + sym_base_type, + STATE(297), 1, + sym_type_name, + ACTIONS(27), 7, + anon_sym_int, + anon_sym_bool, + anon_sym_string, + anon_sym_pubkey, + anon_sym_sig, + anon_sym_datasig, + anon_sym_byte, + [9653] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(652), 1, + sym_identifier, + ACTIONS(656), 1, + anon_sym_LBRACK, + STATE(190), 2, + sym_array_suffix, + aux_sym_type_name_repeat1, + ACTIONS(654), 4, + anon_sym_constant, + anon_sym_LPAREN, + anon_sym_COMMA, + anon_sym_RPAREN, + [9673] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(660), 1, + anon_sym_AMP_AMP, + STATE(194), 1, + aux_sym_logical_and_repeat1, + ACTIONS(658), 6, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_RBRACK, + [9691] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(662), 1, + sym_identifier, + ACTIONS(666), 1, + anon_sym_LBRACK, + STATE(190), 2, + sym_array_suffix, + aux_sym_type_name_repeat1, + ACTIONS(664), 4, + anon_sym_constant, + anon_sym_LPAREN, + anon_sym_COMMA, + anon_sym_RPAREN, + [9711] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(671), 1, + anon_sym_AMP_AMP, + STATE(191), 1, + aux_sym_logical_and_repeat1, + ACTIONS(669), 6, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_RBRACK, + [9729] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(674), 1, + anon_sym_PIPE, + ACTIONS(647), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9745] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(656), 1, + anon_sym_LBRACK, + ACTIONS(676), 1, + sym_identifier, + STATE(188), 2, + sym_array_suffix, + aux_sym_type_name_repeat1, + ACTIONS(678), 4, + anon_sym_constant, + anon_sym_LPAREN, + anon_sym_COMMA, + anon_sym_RPAREN, + [9765] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(660), 1, + anon_sym_AMP_AMP, + STATE(191), 1, + aux_sym_logical_and_repeat1, + ACTIONS(680), 6, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_RBRACK, + [9783] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(684), 1, + anon_sym_PIPE_PIPE, + STATE(195), 1, + aux_sym_logical_or_repeat1, + ACTIONS(682), 5, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_RBRACK, + [9800] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(669), 7, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_AMP_AMP, + anon_sym_RBRACK, + [9813] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(689), 1, + anon_sym_PIPE_PIPE, + STATE(198), 1, + aux_sym_logical_or_repeat1, + ACTIONS(687), 5, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_RBRACK, + [9830] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(689), 1, + anon_sym_PIPE_PIPE, + STATE(195), 1, + aux_sym_logical_or_repeat1, + ACTIONS(691), 5, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_RBRACK, + [9847] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(693), 1, + sym_identifier, + ACTIONS(695), 5, + anon_sym_constant, + anon_sym_LPAREN, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_LBRACK, + [9861] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(697), 1, + sym_identifier, + ACTIONS(699), 5, + anon_sym_constant, + anon_sym_LPAREN, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_LBRACK, + [9875] = 3, + ACTIONS(3), 1, + sym_comment, + STATE(72), 1, + sym_input_field_name, + ACTIONS(701), 5, + anon_sym_value, + anon_sym_scriptPubKey, + anon_sym_outpointTransactionHash, + anon_sym_outpointIndex, + anon_sym_sigScript, + [9889] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(682), 6, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_PIPE_PIPE, + anon_sym_RBRACK, + [9901] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(703), 1, + sym_identifier, + ACTIONS(705), 5, + anon_sym_constant, + anon_sym_LPAREN, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_LBRACK, + [9915] = 6, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + ACTIONS(707), 1, + anon_sym_EQ, + ACTIONS(709), 1, + anon_sym_COLON, + ACTIONS(711), 1, + anon_sym_DOTpush, + STATE(92), 1, + sym_expression_list, + [9934] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(713), 5, + anon_sym_SEMI, + anon_sym_RBRACE, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_RBRACK, + [9945] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(5), 1, + anon_sym_pragma, + ACTIONS(7), 1, + anon_sym_contract, + STATE(363), 1, + sym_contract_definition, + STATE(210), 2, + sym_pragma_directive, + aux_sym_source_file_repeat1, + [9962] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(715), 1, + sym_identifier, + ACTIONS(717), 1, + anon_sym_constant, + STATE(211), 2, + sym_modifier, + aux_sym_variable_definition_repeat1, + [9976] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(717), 1, + anon_sym_constant, + ACTIONS(719), 1, + sym_identifier, + STATE(207), 2, + sym_modifier, + aux_sym_variable_definition_repeat1, + [9990] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(723), 1, + anon_sym_RBRACK, + STATE(341), 1, + sym_array_size, + ACTIONS(721), 2, + sym_array_bound, + sym_identifier, + [10004] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(725), 1, + anon_sym_pragma, + ACTIONS(728), 1, + anon_sym_contract, + STATE(210), 2, + sym_pragma_directive, + aux_sym_source_file_repeat1, + [10018] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(730), 1, + sym_identifier, + ACTIONS(732), 1, + anon_sym_constant, + STATE(211), 2, + sym_modifier, + aux_sym_variable_definition_repeat1, + [10032] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(735), 1, + anon_sym_COMMA, + STATE(212), 1, + aux_sym_expression_list_repeat1, + ACTIONS(738), 2, + anon_sym_RPAREN, + anon_sym_RBRACK, + [10046] = 5, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + ACTIONS(707), 1, + anon_sym_EQ, + ACTIONS(711), 1, + anon_sym_DOTpush, + STATE(92), 1, + sym_expression_list, + [10062] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(740), 1, + anon_sym_COMMA, + ACTIONS(743), 1, + anon_sym_RPAREN, + STATE(214), 1, + aux_sym_console_parameter_list_repeat1, + [10075] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(745), 1, + anon_sym_LBRACE, + ACTIONS(747), 1, + anon_sym_COLON, + STATE(307), 1, + sym_return_type_list, + [10088] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(749), 1, + sym_identifier, + ACTIONS(751), 1, + anon_sym_RBRACE, + STATE(285), 1, + sym_state_typed_binding, + [10101] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(751), 1, + anon_sym_RBRACE, + ACTIONS(753), 1, + anon_sym_COMMA, + STATE(229), 1, + aux_sym_state_function_call_assignment_repeat1, + [10114] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(590), 1, + anon_sym_RPAREN, + ACTIONS(755), 1, + anon_sym_COMMA, + STATE(231), 1, + aux_sym_function_call_assignment_repeat1, + [10127] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(559), 1, + anon_sym_RPAREN, + ACTIONS(757), 1, + anon_sym_COMMA, + STATE(225), 1, + aux_sym_parameter_list_repeat1, + [10140] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(759), 1, + anon_sym_COMMA, + ACTIONS(761), 1, + anon_sym_RPAREN, + STATE(232), 1, + aux_sym_console_parameter_list_repeat1, + [10153] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(631), 1, + anon_sym_RPAREN, + ACTIONS(763), 1, + anon_sym_COMMA, + STATE(233), 1, + aux_sym_return_type_list_repeat1, + [10166] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(765), 1, + sym_identifier, + ACTIONS(767), 1, + anon_sym_RBRACE, + STATE(249), 1, + sym_state_entry, + [10179] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(769), 1, + anon_sym_RBRACE, + ACTIONS(771), 1, + anon_sym_COMMA, + STATE(223), 1, + aux_sym_state_object_repeat1, + [10192] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(738), 3, + anon_sym_COMMA, + anon_sym_RPAREN, + anon_sym_RBRACK, + [10201] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(774), 1, + anon_sym_COMMA, + ACTIONS(777), 1, + anon_sym_RPAREN, + STATE(225), 1, + aux_sym_parameter_list_repeat1, + [10214] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(51), 1, + anon_sym_RPAREN, + ACTIONS(779), 1, + anon_sym_COMMA, + STATE(212), 1, + aux_sym_expression_list_repeat1, + [10227] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(781), 1, + anon_sym_RBRACE, + ACTIONS(783), 1, + anon_sym_COMMA, + STATE(217), 1, + aux_sym_state_function_call_assignment_repeat1, + [10240] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(749), 1, + sym_identifier, + ACTIONS(785), 1, + anon_sym_RBRACE, + STATE(285), 1, + sym_state_typed_binding, + [10253] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(787), 1, + anon_sym_RBRACE, + ACTIONS(789), 1, + anon_sym_COMMA, + STATE(229), 1, + aux_sym_state_function_call_assignment_repeat1, + [10266] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(792), 1, + anon_sym_COMMA, + ACTIONS(794), 1, + anon_sym_RPAREN, + STATE(218), 1, + aux_sym_function_call_assignment_repeat1, + [10279] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(796), 1, + anon_sym_COMMA, + ACTIONS(799), 1, + anon_sym_RPAREN, + STATE(231), 1, + aux_sym_function_call_assignment_repeat1, + [10292] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(534), 1, + anon_sym_RPAREN, + ACTIONS(801), 1, + anon_sym_COMMA, + STATE(214), 1, + aux_sym_console_parameter_list_repeat1, + [10305] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(803), 1, + anon_sym_COMMA, + ACTIONS(806), 1, + anon_sym_RPAREN, + STATE(233), 1, + aux_sym_return_type_list_repeat1, + [10318] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(808), 1, + anon_sym_SEMI, + ACTIONS(810), 1, + anon_sym_EQ, + ACTIONS(812), 1, + anon_sym_COMMA, + [10331] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(814), 1, + anon_sym_COMMA, + ACTIONS(816), 1, + anon_sym_RPAREN, + STATE(221), 1, + aux_sym_return_type_list_repeat1, + [10344] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(765), 1, + sym_identifier, + ACTIONS(818), 1, + anon_sym_RBRACE, + STATE(249), 1, + sym_state_entry, + [10357] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(818), 1, + anon_sym_RBRACE, + ACTIONS(820), 1, + anon_sym_COMMA, + STATE(223), 1, + aux_sym_state_object_repeat1, + [10370] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(47), 1, + anon_sym_RBRACK, + ACTIONS(822), 1, + anon_sym_COMMA, + STATE(212), 1, + aux_sym_expression_list_repeat1, + [10383] = 3, + ACTIONS(3), 1, + sym_comment, + STATE(70), 1, + sym_output_field_name, + ACTIONS(824), 2, + anon_sym_value, + anon_sym_scriptPubKey, + [10394] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(826), 1, + anon_sym_COMMA, + ACTIONS(828), 1, + anon_sym_RPAREN, + STATE(226), 1, + aux_sym_expression_list_repeat1, + [10407] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(747), 1, + anon_sym_COLON, + ACTIONS(830), 1, + anon_sym_LBRACE, + STATE(387), 1, + sym_return_type_list, + [10420] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(832), 1, + anon_sym_RBRACE, + ACTIONS(834), 1, + anon_sym_COMMA, + STATE(237), 1, + aux_sym_state_object_repeat1, + [10433] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(836), 1, + anon_sym_COMMA, + ACTIONS(838), 1, + anon_sym_RBRACK, + STATE(238), 1, + aux_sym_expression_list_repeat1, + [10446] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(840), 1, + anon_sym_COMMA, + ACTIONS(842), 1, + anon_sym_RPAREN, + STATE(219), 1, + aux_sym_parameter_list_repeat1, + [10459] = 4, + ACTIONS(3), 1, + sym_comment, + ACTIONS(765), 1, + sym_identifier, + ACTIONS(844), 1, + anon_sym_RBRACE, + STATE(242), 1, + sym_state_entry, + [10472] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(846), 1, + anon_sym_LBRACK, + STATE(288), 1, + sym_tuple_index, + [10482] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(848), 1, + sym_identifier, + STATE(321), 1, + sym_function_call, + [10492] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(850), 2, + anon_sym_RBRACE, + anon_sym_COMMA, + [10500] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(769), 2, + anon_sym_RBRACE, + anon_sym_COMMA, + [10508] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(852), 1, + sym_string_literal, + STATE(325), 1, + sym_require_message, + [10518] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(846), 1, + anon_sym_LBRACK, + STATE(289), 1, + sym_tuple_index, + [10528] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(806), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10536] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(854), 1, + anon_sym_COMMA, + ACTIONS(856), 1, + anon_sym_RPAREN, + [10546] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(858), 1, + anon_sym_LPAREN, + STATE(241), 1, + sym_parameter_list, + [10556] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(765), 1, + sym_identifier, + STATE(249), 1, + sym_state_entry, + [10566] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(860), 1, + sym_identifier, + ACTIONS(862), 1, + anon_sym_constant, + [10576] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(864), 1, + sym_identifier, + ACTIONS(866), 1, + anon_sym_constant, + [10586] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(749), 1, + sym_identifier, + STATE(227), 1, + sym_state_typed_binding, + [10596] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(868), 1, + anon_sym_COMMA, + ACTIONS(870), 1, + anon_sym_RPAREN, + [10606] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(872), 2, + anon_sym_RBRACE, + anon_sym_COMMA, + [10614] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + STATE(92), 1, + sym_expression_list, + [10624] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(848), 1, + sym_identifier, + STATE(347), 1, + sym_function_call, + [10634] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(749), 1, + sym_identifier, + STATE(285), 1, + sym_state_typed_binding, + [10644] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(848), 1, + sym_identifier, + STATE(349), 1, + sym_function_call, + [10654] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(874), 1, + anon_sym_COMMA, + ACTIONS(876), 1, + anon_sym_RPAREN, + [10664] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(799), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10672] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + STATE(379), 1, + sym_expression_list, + [10682] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(743), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10690] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(878), 2, + anon_sym_LBRACE, + anon_sym_COLON, + [10698] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(777), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10706] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + STATE(298), 1, + sym_expression_list, + [10716] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(880), 1, + anon_sym_LPAREN, + STATE(302), 1, + sym_console_parameter_list, + [10726] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(882), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10734] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(848), 1, + sym_identifier, + STATE(368), 1, + sym_function_call, + [10744] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(858), 1, + anon_sym_LPAREN, + STATE(320), 1, + sym_parameter_list, + [10754] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(848), 1, + sym_identifier, + STATE(370), 1, + sym_function_call, + [10764] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(852), 1, + sym_string_literal, + STATE(372), 1, + sym_require_message, + [10774] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(884), 2, + anon_sym_pragma, + anon_sym_contract, + [10782] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(886), 2, + anon_sym_LBRACE, + anon_sym_COLON, + [10790] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(888), 2, + anon_sym_LBRACE, + anon_sym_COLON, + [10798] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(890), 2, + anon_sym_LBRACE, + anon_sym_COLON, + [10806] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(858), 1, + anon_sym_LPAREN, + STATE(215), 1, + sym_parameter_list, + [10816] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(892), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10824] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(848), 1, + sym_identifier, + STATE(316), 1, + sym_function_call, + [10834] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(787), 2, + anon_sym_RBRACE, + anon_sym_COMMA, + [10842] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(188), 1, + anon_sym_LPAREN, + STATE(64), 1, + sym_expression_list, + [10852] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(894), 1, + anon_sym_SEMI, + ACTIONS(896), 1, + anon_sym_EQ, + [10862] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(898), 1, + anon_sym_DOT, + STATE(66), 1, + sym_output_field, + [10872] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(900), 1, + anon_sym_DOT, + STATE(66), 1, + sym_input_field, + [10882] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(902), 2, + anon_sym_COMMA, + anon_sym_RPAREN, + [10890] = 3, + ACTIONS(3), 1, + sym_comment, + ACTIONS(904), 1, + anon_sym_COMMA, + ACTIONS(906), 1, + anon_sym_RPAREN, + [10900] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(908), 1, + anon_sym_LPAREN, + [10907] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(910), 1, + sym_version_literal, + [10914] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(912), 1, + sym_identifier, + [10921] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(914), 1, + anon_sym_RPAREN, + [10928] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(916), 1, + anon_sym_SEMI, + [10935] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(918), 1, + sym_identifier, + [10942] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(920), 1, + anon_sym_SEMI, + [10949] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(922), 1, + sym_identifier, + [10956] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(924), 1, + anon_sym_LBRACE, + [10963] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(926), 1, + anon_sym_GT_EQ, + [10970] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(928), 1, + anon_sym_SEMI, + [10977] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(930), 1, + anon_sym_RPAREN, + [10984] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(932), 1, + anon_sym_COMMA, + [10991] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(934), 1, + sym_version_literal, + [10998] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(936), 1, + ts_builtin_sym_end, + [11005] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(938), 1, + anon_sym_LBRACE, + [11012] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(940), 1, + anon_sym_SEMI, + [11019] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(942), 1, + sym_identifier, + [11026] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(944), 1, + anon_sym_LPAREN, + [11033] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(946), 1, + sym_identifier, + [11040] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(948), 1, + anon_sym_EQ, + [11047] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(322), 1, + anon_sym_DOT, + [11054] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(950), 1, + anon_sym_LPAREN, + [11061] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(952), 1, + anon_sym_LPAREN, + [11068] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(954), 1, + anon_sym_SEMI, + [11075] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(956), 1, + anon_sym_EQ, + [11082] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(958), 1, + anon_sym_EQ, + [11089] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(960), 1, + sym_identifier, + [11096] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(962), 1, + anon_sym_LBRACE, + [11103] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(964), 1, + anon_sym_SEMI, + [11110] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(966), 1, + anon_sym_EQ, + [11117] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(968), 1, + anon_sym_LBRACE, + [11124] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(970), 1, + anon_sym_RPAREN, + [11131] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(972), 1, + anon_sym_RPAREN, + [11138] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(974), 1, + anon_sym_EQ, + [11145] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(976), 1, + anon_sym_SEMI, + [11152] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(978), 1, + anon_sym_SEMI, + [11159] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(980), 1, + anon_sym_LPAREN, + [11166] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(982), 1, + anon_sym_LPAREN, + [11173] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(984), 1, + anon_sym_COMMA, + [11180] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(986), 1, + anon_sym_SEMI, + [11187] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(988), 1, + anon_sym_RPAREN, + [11194] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(990), 1, + anon_sym_LPAREN, + [11201] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(992), 1, + anon_sym_COMMA, + [11208] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(994), 1, + anon_sym_SEMI, + [11215] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(996), 1, + anon_sym_RBRACK, + [11222] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(998), 1, + anon_sym_EQ, + [11229] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1000), 1, + anon_sym_SEMI, + [11236] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1002), 1, + anon_sym_LBRACE, + [11243] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1004), 1, + anon_sym_RBRACK, + [11250] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(709), 1, + anon_sym_COLON, + [11257] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1006), 1, + anon_sym_RPAREN, + [11264] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1008), 1, + anon_sym_SEMI, + [11271] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1010), 1, + ts_builtin_sym_end, + [11278] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1012), 1, + anon_sym_LPAREN, + [11285] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1014), 1, + anon_sym_SEMI, + [11292] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1016), 1, + sym_identifier, + [11299] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1018), 1, + anon_sym_SEMI, + [11306] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1020), 1, + anon_sym_silverscript, + [11313] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1022), 1, + anon_sym_EQ, + [11320] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1024), 1, + anon_sym_SEMI, + [11327] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1026), 1, + ts_builtin_sym_end, + [11334] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1028), 1, + anon_sym_SEMI, + [11341] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1030), 1, + anon_sym_RBRACK, + [11348] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1032), 1, + anon_sym_RPAREN, + [11355] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1034), 1, + anon_sym_SEMI, + [11362] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1036), 1, + anon_sym_SEMI, + [11369] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1038), 1, + anon_sym_RPAREN, + [11376] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1040), 1, + anon_sym_SEMI, + [11383] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1042), 1, + anon_sym_EQ, + [11390] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1044), 1, + anon_sym_function, + [11397] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1046), 1, + ts_builtin_sym_end, + [11404] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1048), 1, + anon_sym_LBRACE, + [11411] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1050), 1, + anon_sym_SEMI, + [11418] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1052), 1, + anon_sym_GT_EQ, + [11425] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1054), 1, + anon_sym_COLON, + [11432] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1056), 1, + anon_sym_SEMI, + [11439] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1058), 1, + sym_identifier, + [11446] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1060), 1, + anon_sym_SEMI, + [11453] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1062), 1, + anon_sym_RPAREN, + [11460] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1064), 1, + anon_sym_RPAREN, + [11467] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1066), 1, + anon_sym_EQ, + [11474] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1068), 1, + ts_builtin_sym_end, + [11481] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1070), 1, + anon_sym_SEMI, + [11488] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1072), 1, + anon_sym_RPAREN, + [11495] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1074), 1, + anon_sym_SEMI, + [11502] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1076), 1, + sym_identifier, + [11509] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1078), 1, + anon_sym_SEMI, + [11516] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1080), 1, + anon_sym_SEMI, + [11523] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1082), 1, + anon_sym_SEMI, + [11530] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1084), 1, + anon_sym_LPAREN, + [11537] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1086), 1, + sym_identifier, + [11544] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1088), 1, + sym_string_literal, + [11551] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1090), 1, + anon_sym_LPAREN, + [11558] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1092), 1, + anon_sym_RBRACK, + [11565] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1094), 1, + anon_sym_LBRACE, + [11572] = 2, + ACTIONS(3), 1, + sym_comment, + ACTIONS(1096), 1, + anon_sym_RPAREN, +}; + +static const uint32_t ts_small_parse_table_map[] = { + [SMALL_STATE(2)] = 0, + [SMALL_STATE(3)] = 138, + [SMALL_STATE(4)] = 272, + [SMALL_STATE(5)] = 406, + [SMALL_STATE(6)] = 540, + [SMALL_STATE(7)] = 674, + [SMALL_STATE(8)] = 808, + [SMALL_STATE(9)] = 942, + [SMALL_STATE(10)] = 1076, + [SMALL_STATE(11)] = 1207, + [SMALL_STATE(12)] = 1338, + [SMALL_STATE(13)] = 1469, + [SMALL_STATE(14)] = 1600, + [SMALL_STATE(15)] = 1731, + [SMALL_STATE(16)] = 1862, + [SMALL_STATE(17)] = 1993, + [SMALL_STATE(18)] = 2124, + [SMALL_STATE(19)] = 2255, + [SMALL_STATE(20)] = 2386, + [SMALL_STATE(21)] = 2517, + [SMALL_STATE(22)] = 2648, + [SMALL_STATE(23)] = 2779, + [SMALL_STATE(24)] = 2910, + [SMALL_STATE(25)] = 3041, + [SMALL_STATE(26)] = 3172, + [SMALL_STATE(27)] = 3303, + [SMALL_STATE(28)] = 3434, + [SMALL_STATE(29)] = 3565, + [SMALL_STATE(30)] = 3696, + [SMALL_STATE(31)] = 3821, + [SMALL_STATE(32)] = 3943, + [SMALL_STATE(33)] = 4062, + [SMALL_STATE(34)] = 4178, + [SMALL_STATE(35)] = 4291, + [SMALL_STATE(36)] = 4401, + [SMALL_STATE(37)] = 4508, + [SMALL_STATE(38)] = 4612, + [SMALL_STATE(39)] = 4713, + [SMALL_STATE(40)] = 4811, + [SMALL_STATE(41)] = 4886, + [SMALL_STATE(42)] = 4958, + [SMALL_STATE(43)] = 5030, + [SMALL_STATE(44)] = 5102, + [SMALL_STATE(45)] = 5174, + [SMALL_STATE(46)] = 5246, + [SMALL_STATE(47)] = 5318, + [SMALL_STATE(48)] = 5390, + [SMALL_STATE(49)] = 5462, + [SMALL_STATE(50)] = 5534, + [SMALL_STATE(51)] = 5606, + [SMALL_STATE(52)] = 5677, + [SMALL_STATE(53)] = 5748, + [SMALL_STATE(54)] = 5795, + [SMALL_STATE(55)] = 5866, + [SMALL_STATE(56)] = 5920, + [SMALL_STATE(57)] = 5974, + [SMALL_STATE(58)] = 6028, + [SMALL_STATE(59)] = 6074, + [SMALL_STATE(60)] = 6112, + [SMALL_STATE(61)] = 6152, + [SMALL_STATE(62)] = 6186, + [SMALL_STATE(63)] = 6220, + [SMALL_STATE(64)] = 6254, + [SMALL_STATE(65)] = 6288, + [SMALL_STATE(66)] = 6322, + [SMALL_STATE(67)] = 6356, + [SMALL_STATE(68)] = 6390, + [SMALL_STATE(69)] = 6424, + [SMALL_STATE(70)] = 6458, + [SMALL_STATE(71)] = 6492, + [SMALL_STATE(72)] = 6526, + [SMALL_STATE(73)] = 6560, + [SMALL_STATE(74)] = 6594, + [SMALL_STATE(75)] = 6628, + [SMALL_STATE(76)] = 6662, + [SMALL_STATE(77)] = 6696, + [SMALL_STATE(78)] = 6730, + [SMALL_STATE(79)] = 6764, + [SMALL_STATE(80)] = 6798, + [SMALL_STATE(81)] = 6832, + [SMALL_STATE(82)] = 6866, + [SMALL_STATE(83)] = 6900, + [SMALL_STATE(84)] = 6934, + [SMALL_STATE(85)] = 6968, + [SMALL_STATE(86)] = 7002, + [SMALL_STATE(87)] = 7036, + [SMALL_STATE(88)] = 7070, + [SMALL_STATE(89)] = 7104, + [SMALL_STATE(90)] = 7138, + [SMALL_STATE(91)] = 7172, + [SMALL_STATE(92)] = 7206, + [SMALL_STATE(93)] = 7240, + [SMALL_STATE(94)] = 7274, + [SMALL_STATE(95)] = 7308, + [SMALL_STATE(96)] = 7342, + [SMALL_STATE(97)] = 7376, + [SMALL_STATE(98)] = 7412, + [SMALL_STATE(99)] = 7448, + [SMALL_STATE(100)] = 7484, + [SMALL_STATE(101)] = 7513, + [SMALL_STATE(102)] = 7542, + [SMALL_STATE(103)] = 7571, + [SMALL_STATE(104)] = 7602, + [SMALL_STATE(105)] = 7633, + [SMALL_STATE(106)] = 7664, + [SMALL_STATE(107)] = 7690, + [SMALL_STATE(108)] = 7716, + [SMALL_STATE(109)] = 7742, + [SMALL_STATE(110)] = 7768, + [SMALL_STATE(111)] = 7794, + [SMALL_STATE(112)] = 7820, + [SMALL_STATE(113)] = 7846, + [SMALL_STATE(114)] = 7872, + [SMALL_STATE(115)] = 7898, + [SMALL_STATE(116)] = 7924, + [SMALL_STATE(117)] = 7950, + [SMALL_STATE(118)] = 7978, + [SMALL_STATE(119)] = 8004, + [SMALL_STATE(120)] = 8030, + [SMALL_STATE(121)] = 8056, + [SMALL_STATE(122)] = 8082, + [SMALL_STATE(123)] = 8108, + [SMALL_STATE(124)] = 8134, + [SMALL_STATE(125)] = 8160, + [SMALL_STATE(126)] = 8186, + [SMALL_STATE(127)] = 8212, + [SMALL_STATE(128)] = 8238, + [SMALL_STATE(129)] = 8264, + [SMALL_STATE(130)] = 8290, + [SMALL_STATE(131)] = 8316, + [SMALL_STATE(132)] = 8342, + [SMALL_STATE(133)] = 8368, + [SMALL_STATE(134)] = 8394, + [SMALL_STATE(135)] = 8420, + [SMALL_STATE(136)] = 8451, + [SMALL_STATE(137)] = 8488, + [SMALL_STATE(138)] = 8525, + [SMALL_STATE(139)] = 8562, + [SMALL_STATE(140)] = 8593, + [SMALL_STATE(141)] = 8624, + [SMALL_STATE(142)] = 8648, + [SMALL_STATE(143)] = 8683, + [SMALL_STATE(144)] = 8708, + [SMALL_STATE(145)] = 8743, + [SMALL_STATE(146)] = 8768, + [SMALL_STATE(147)] = 8793, + [SMALL_STATE(148)] = 8828, + [SMALL_STATE(149)] = 8848, + [SMALL_STATE(150)] = 8880, + [SMALL_STATE(151)] = 8905, + [SMALL_STATE(152)] = 8930, + [SMALL_STATE(153)] = 8953, + [SMALL_STATE(154)] = 8976, + [SMALL_STATE(155)] = 9001, + [SMALL_STATE(156)] = 9024, + [SMALL_STATE(157)] = 9049, + [SMALL_STATE(158)] = 9076, + [SMALL_STATE(159)] = 9101, + [SMALL_STATE(160)] = 9128, + [SMALL_STATE(161)] = 9144, + [SMALL_STATE(162)] = 9166, + [SMALL_STATE(163)] = 9188, + [SMALL_STATE(164)] = 9210, + [SMALL_STATE(165)] = 9226, + [SMALL_STATE(166)] = 9244, + [SMALL_STATE(167)] = 9266, + [SMALL_STATE(168)] = 9282, + [SMALL_STATE(169)] = 9298, + [SMALL_STATE(170)] = 9314, + [SMALL_STATE(171)] = 9330, + [SMALL_STATE(172)] = 9352, + [SMALL_STATE(173)] = 9374, + [SMALL_STATE(174)] = 9390, + [SMALL_STATE(175)] = 9412, + [SMALL_STATE(176)] = 9428, + [SMALL_STATE(177)] = 9450, + [SMALL_STATE(178)] = 9466, + [SMALL_STATE(179)] = 9488, + [SMALL_STATE(180)] = 9505, + [SMALL_STATE(181)] = 9522, + [SMALL_STATE(182)] = 9541, + [SMALL_STATE(183)] = 9560, + [SMALL_STATE(184)] = 9579, + [SMALL_STATE(185)] = 9598, + [SMALL_STATE(186)] = 9617, + [SMALL_STATE(187)] = 9634, + [SMALL_STATE(188)] = 9653, + [SMALL_STATE(189)] = 9673, + [SMALL_STATE(190)] = 9691, + [SMALL_STATE(191)] = 9711, + [SMALL_STATE(192)] = 9729, + [SMALL_STATE(193)] = 9745, + [SMALL_STATE(194)] = 9765, + [SMALL_STATE(195)] = 9783, + [SMALL_STATE(196)] = 9800, + [SMALL_STATE(197)] = 9813, + [SMALL_STATE(198)] = 9830, + [SMALL_STATE(199)] = 9847, + [SMALL_STATE(200)] = 9861, + [SMALL_STATE(201)] = 9875, + [SMALL_STATE(202)] = 9889, + [SMALL_STATE(203)] = 9901, + [SMALL_STATE(204)] = 9915, + [SMALL_STATE(205)] = 9934, + [SMALL_STATE(206)] = 9945, + [SMALL_STATE(207)] = 9962, + [SMALL_STATE(208)] = 9976, + [SMALL_STATE(209)] = 9990, + [SMALL_STATE(210)] = 10004, + [SMALL_STATE(211)] = 10018, + [SMALL_STATE(212)] = 10032, + [SMALL_STATE(213)] = 10046, + [SMALL_STATE(214)] = 10062, + [SMALL_STATE(215)] = 10075, + [SMALL_STATE(216)] = 10088, + [SMALL_STATE(217)] = 10101, + [SMALL_STATE(218)] = 10114, + [SMALL_STATE(219)] = 10127, + [SMALL_STATE(220)] = 10140, + [SMALL_STATE(221)] = 10153, + [SMALL_STATE(222)] = 10166, + [SMALL_STATE(223)] = 10179, + [SMALL_STATE(224)] = 10192, + [SMALL_STATE(225)] = 10201, + [SMALL_STATE(226)] = 10214, + [SMALL_STATE(227)] = 10227, + [SMALL_STATE(228)] = 10240, + [SMALL_STATE(229)] = 10253, + [SMALL_STATE(230)] = 10266, + [SMALL_STATE(231)] = 10279, + [SMALL_STATE(232)] = 10292, + [SMALL_STATE(233)] = 10305, + [SMALL_STATE(234)] = 10318, + [SMALL_STATE(235)] = 10331, + [SMALL_STATE(236)] = 10344, + [SMALL_STATE(237)] = 10357, + [SMALL_STATE(238)] = 10370, + [SMALL_STATE(239)] = 10383, + [SMALL_STATE(240)] = 10394, + [SMALL_STATE(241)] = 10407, + [SMALL_STATE(242)] = 10420, + [SMALL_STATE(243)] = 10433, + [SMALL_STATE(244)] = 10446, + [SMALL_STATE(245)] = 10459, + [SMALL_STATE(246)] = 10472, + [SMALL_STATE(247)] = 10482, + [SMALL_STATE(248)] = 10492, + [SMALL_STATE(249)] = 10500, + [SMALL_STATE(250)] = 10508, + [SMALL_STATE(251)] = 10518, + [SMALL_STATE(252)] = 10528, + [SMALL_STATE(253)] = 10536, + [SMALL_STATE(254)] = 10546, + [SMALL_STATE(255)] = 10556, + [SMALL_STATE(256)] = 10566, + [SMALL_STATE(257)] = 10576, + [SMALL_STATE(258)] = 10586, + [SMALL_STATE(259)] = 10596, + [SMALL_STATE(260)] = 10606, + [SMALL_STATE(261)] = 10614, + [SMALL_STATE(262)] = 10624, + [SMALL_STATE(263)] = 10634, + [SMALL_STATE(264)] = 10644, + [SMALL_STATE(265)] = 10654, + [SMALL_STATE(266)] = 10664, + [SMALL_STATE(267)] = 10672, + [SMALL_STATE(268)] = 10682, + [SMALL_STATE(269)] = 10690, + [SMALL_STATE(270)] = 10698, + [SMALL_STATE(271)] = 10706, + [SMALL_STATE(272)] = 10716, + [SMALL_STATE(273)] = 10726, + [SMALL_STATE(274)] = 10734, + [SMALL_STATE(275)] = 10744, + [SMALL_STATE(276)] = 10754, + [SMALL_STATE(277)] = 10764, + [SMALL_STATE(278)] = 10774, + [SMALL_STATE(279)] = 10782, + [SMALL_STATE(280)] = 10790, + [SMALL_STATE(281)] = 10798, + [SMALL_STATE(282)] = 10806, + [SMALL_STATE(283)] = 10816, + [SMALL_STATE(284)] = 10824, + [SMALL_STATE(285)] = 10834, + [SMALL_STATE(286)] = 10842, + [SMALL_STATE(287)] = 10852, + [SMALL_STATE(288)] = 10862, + [SMALL_STATE(289)] = 10872, + [SMALL_STATE(290)] = 10882, + [SMALL_STATE(291)] = 10890, + [SMALL_STATE(292)] = 10900, + [SMALL_STATE(293)] = 10907, + [SMALL_STATE(294)] = 10914, + [SMALL_STATE(295)] = 10921, + [SMALL_STATE(296)] = 10928, + [SMALL_STATE(297)] = 10935, + [SMALL_STATE(298)] = 10942, + [SMALL_STATE(299)] = 10949, + [SMALL_STATE(300)] = 10956, + [SMALL_STATE(301)] = 10963, + [SMALL_STATE(302)] = 10970, + [SMALL_STATE(303)] = 10977, + [SMALL_STATE(304)] = 10984, + [SMALL_STATE(305)] = 10991, + [SMALL_STATE(306)] = 10998, + [SMALL_STATE(307)] = 11005, + [SMALL_STATE(308)] = 11012, + [SMALL_STATE(309)] = 11019, + [SMALL_STATE(310)] = 11026, + [SMALL_STATE(311)] = 11033, + [SMALL_STATE(312)] = 11040, + [SMALL_STATE(313)] = 11047, + [SMALL_STATE(314)] = 11054, + [SMALL_STATE(315)] = 11061, + [SMALL_STATE(316)] = 11068, + [SMALL_STATE(317)] = 11075, + [SMALL_STATE(318)] = 11082, + [SMALL_STATE(319)] = 11089, + [SMALL_STATE(320)] = 11096, + [SMALL_STATE(321)] = 11103, + [SMALL_STATE(322)] = 11110, + [SMALL_STATE(323)] = 11117, + [SMALL_STATE(324)] = 11124, + [SMALL_STATE(325)] = 11131, + [SMALL_STATE(326)] = 11138, + [SMALL_STATE(327)] = 11145, + [SMALL_STATE(328)] = 11152, + [SMALL_STATE(329)] = 11159, + [SMALL_STATE(330)] = 11166, + [SMALL_STATE(331)] = 11173, + [SMALL_STATE(332)] = 11180, + [SMALL_STATE(333)] = 11187, + [SMALL_STATE(334)] = 11194, + [SMALL_STATE(335)] = 11201, + [SMALL_STATE(336)] = 11208, + [SMALL_STATE(337)] = 11215, + [SMALL_STATE(338)] = 11222, + [SMALL_STATE(339)] = 11229, + [SMALL_STATE(340)] = 11236, + [SMALL_STATE(341)] = 11243, + [SMALL_STATE(342)] = 11250, + [SMALL_STATE(343)] = 11257, + [SMALL_STATE(344)] = 11264, + [SMALL_STATE(345)] = 11271, + [SMALL_STATE(346)] = 11278, + [SMALL_STATE(347)] = 11285, + [SMALL_STATE(348)] = 11292, + [SMALL_STATE(349)] = 11299, + [SMALL_STATE(350)] = 11306, + [SMALL_STATE(351)] = 11313, + [SMALL_STATE(352)] = 11320, + [SMALL_STATE(353)] = 11327, + [SMALL_STATE(354)] = 11334, + [SMALL_STATE(355)] = 11341, + [SMALL_STATE(356)] = 11348, + [SMALL_STATE(357)] = 11355, + [SMALL_STATE(358)] = 11362, + [SMALL_STATE(359)] = 11369, + [SMALL_STATE(360)] = 11376, + [SMALL_STATE(361)] = 11383, + [SMALL_STATE(362)] = 11390, + [SMALL_STATE(363)] = 11397, + [SMALL_STATE(364)] = 11404, + [SMALL_STATE(365)] = 11411, + [SMALL_STATE(366)] = 11418, + [SMALL_STATE(367)] = 11425, + [SMALL_STATE(368)] = 11432, + [SMALL_STATE(369)] = 11439, + [SMALL_STATE(370)] = 11446, + [SMALL_STATE(371)] = 11453, + [SMALL_STATE(372)] = 11460, + [SMALL_STATE(373)] = 11467, + [SMALL_STATE(374)] = 11474, + [SMALL_STATE(375)] = 11481, + [SMALL_STATE(376)] = 11488, + [SMALL_STATE(377)] = 11495, + [SMALL_STATE(378)] = 11502, + [SMALL_STATE(379)] = 11509, + [SMALL_STATE(380)] = 11516, + [SMALL_STATE(381)] = 11523, + [SMALL_STATE(382)] = 11530, + [SMALL_STATE(383)] = 11537, + [SMALL_STATE(384)] = 11544, + [SMALL_STATE(385)] = 11551, + [SMALL_STATE(386)] = 11558, + [SMALL_STATE(387)] = 11565, + [SMALL_STATE(388)] = 11572, +}; + +static const TSParseActionEntry ts_parse_actions[] = { + [0] = {.entry = {.count = 0, .reusable = false}}, + [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), + [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT_EXTRA(), + [5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(350), + [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(309), + [9] = {.entry = {.count = 1, .reusable = false}}, SHIFT(60), + [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(245), + [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(26), + [15] = {.entry = {.count = 1, .reusable = false}}, SHIFT(59), + [17] = {.entry = {.count = 1, .reusable = true}}, SHIFT(59), + [19] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4), + [21] = {.entry = {.count = 1, .reusable = true}}, SHIFT(319), + [23] = {.entry = {.count = 1, .reusable = false}}, SHIFT(246), + [25] = {.entry = {.count = 1, .reusable = false}}, SHIFT(251), + [27] = {.entry = {.count = 1, .reusable = true}}, SHIFT(203), + [29] = {.entry = {.count = 1, .reusable = true}}, SHIFT(65), + [31] = {.entry = {.count = 1, .reusable = false}}, SHIFT(53), + [33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(61), + [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(346), + [37] = {.entry = {.count = 1, .reusable = true}}, SHIFT(366), + [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(87), + [41] = {.entry = {.count = 1, .reusable = false}}, SHIFT(87), + [43] = {.entry = {.count = 1, .reusable = true}}, SHIFT(96), + [45] = {.entry = {.count = 1, .reusable = true}}, SHIFT(85), + [47] = {.entry = {.count = 1, .reusable = true}}, SHIFT(68), + [49] = {.entry = {.count = 1, .reusable = true}}, SHIFT(82), + [51] = {.entry = {.count = 1, .reusable = true}}, SHIFT(83), + [53] = {.entry = {.count = 1, .reusable = true}}, SHIFT(86), + [55] = {.entry = {.count = 1, .reusable = true}}, SHIFT(89), + [57] = {.entry = {.count = 1, .reusable = false}}, SHIFT(204), + [59] = {.entry = {.count = 1, .reusable = true}}, SHIFT(258), + [61] = {.entry = {.count = 1, .reusable = true}}, SHIFT(122), + [63] = {.entry = {.count = 1, .reusable = true}}, SHIFT(162), + [65] = {.entry = {.count = 1, .reusable = true}}, SHIFT(267), + [67] = {.entry = {.count = 1, .reusable = true}}, SHIFT(329), + [69] = {.entry = {.count = 1, .reusable = true}}, SHIFT(330), + [71] = {.entry = {.count = 1, .reusable = true}}, SHIFT(334), + [73] = {.entry = {.count = 1, .reusable = true}}, SHIFT(271), + [75] = {.entry = {.count = 1, .reusable = true}}, SHIFT(272), + [77] = {.entry = {.count = 1, .reusable = false}}, SHIFT(213), + [79] = {.entry = {.count = 1, .reusable = true}}, SHIFT(129), + [81] = {.entry = {.count = 1, .reusable = true}}, SHIFT(169), + [83] = {.entry = {.count = 1, .reusable = true}}, SHIFT(160), + [85] = {.entry = {.count = 1, .reusable = true}}, SHIFT(168), + [87] = {.entry = {.count = 1, .reusable = true}}, SHIFT(175), + [89] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(213), + [92] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(258), + [95] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), + [97] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(162), + [100] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(267), + [103] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(329), + [106] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(330), + [109] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(334), + [112] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(271), + [115] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(272), + [118] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(203), + [121] = {.entry = {.count = 1, .reusable = true}}, SHIFT(173), + [123] = {.entry = {.count = 1, .reusable = true}}, SHIFT(164), + [125] = {.entry = {.count = 1, .reusable = true}}, SHIFT(40), + [127] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number_literal, 1, 0, 0), + [129] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number_literal, 1, 0, 0), + [131] = {.entry = {.count = 1, .reusable = true}}, SHIFT(88), + [133] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_postfix, 2, 0, 0), + [135] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_postfix, 2, 0, 0), + [137] = {.entry = {.count = 1, .reusable = true}}, SHIFT(28), + [139] = {.entry = {.count = 1, .reusable = true}}, SHIFT(78), + [141] = {.entry = {.count = 1, .reusable = true}}, SHIFT(310), + [143] = {.entry = {.count = 1, .reusable = true}}, SHIFT(314), + [145] = {.entry = {.count = 1, .reusable = true}}, SHIFT(315), + [147] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_postfix, 1, 0, 0), + [149] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_postfix, 1, 0, 0), + [151] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), + [153] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), + [155] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), SHIFT_REPEAT(28), + [158] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), SHIFT_REPEAT(78), + [161] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), SHIFT_REPEAT(310), + [164] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), SHIFT_REPEAT(314), + [167] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_postfix_repeat1, 2, 0, 0), SHIFT_REPEAT(315), + [170] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_unary_repeat1, 2, 0, 0), + [172] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_unary_repeat1, 2, 0, 0), + [174] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_unary_repeat1, 2, 0, 0), SHIFT_REPEAT(59), + [177] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_unary_repeat1, 2, 0, 0), SHIFT_REPEAT(59), + [180] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary_op, 1, 0, 0), + [182] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary_op, 1, 0, 0), + [184] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_primary, 1, 0, 0), + [186] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_primary, 1, 0, 0), + [188] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3), + [190] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_literal, 1, 0, 0), + [192] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_literal, 1, 0, 0), + [194] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array, 3, 0, 0), + [196] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_array, 3, 0, 0), + [198] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_instantiation, 3, 0, 0), + [200] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_instantiation, 3, 0, 0), + [202] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_boolean_literal, 1, 0, 0), + [204] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_boolean_literal, 1, 0, 0), + [206] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_introspection, 3, 0, 5), + [208] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_introspection, 3, 0, 5), + [210] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_object, 4, 0, 0), + [212] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_object, 4, 0, 0), + [214] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array, 4, 0, 0), + [216] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_array, 4, 0, 0), + [218] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_output_field_name, 1, 0, 0), + [220] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_output_field_name, 1, 0, 0), + [222] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_output_field, 2, 0, 1), + [224] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_output_field, 2, 0, 1), + [226] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_input_field_name, 1, 0, 0), + [228] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_input_field_name, 1, 0, 0), + [230] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_input_field, 2, 0, 1), + [232] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_input_field, 2, 0, 1), + [234] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_date_literal, 4, 0, 0), + [236] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_date_literal, 4, 0, 0), + [238] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_object, 3, 0, 0), + [240] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_object, 3, 0, 0), + [242] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression_list, 3, 0, 0), + [244] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression_list, 3, 0, 0), + [246] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_reverse_call, 3, 0, 0), + [248] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_reverse_call, 3, 0, 0), + [250] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_cast, 4, 0, 0), + [252] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_cast, 4, 0, 0), + [254] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_postfix_op, 1, 0, 0), + [256] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_postfix_op, 1, 0, 0), + [258] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parenthesized, 3, 0, 0), + [260] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_parenthesized, 3, 0, 0), + [262] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_object, 2, 0, 0), + [264] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_object, 2, 0, 0), + [266] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_object, 5, 0, 0), + [268] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_object, 5, 0, 0), + [270] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array, 5, 0, 0), + [272] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_array, 5, 0, 0), + [274] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression_list, 4, 0, 0), + [276] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression_list, 4, 0, 0), + [278] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_split_call, 4, 0, 0), + [280] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_split_call, 4, 0, 0), + [282] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array, 2, 0, 0), + [284] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_array, 2, 0, 0), + [286] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_cast, 5, 0, 0), + [288] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_cast, 5, 0, 0), + [290] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_nullary_op, 1, 0, 0), + [292] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_nullary_op, 1, 0, 0), + [294] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number_unit, 1, 0, 0), + [296] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number_unit, 1, 0, 0), + [298] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression_list, 5, 0, 0), + [300] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression_list, 5, 0, 0), + [302] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_cast, 6, 0, 0), + [304] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_cast, 6, 0, 0), + [306] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_number_literal, 2, 0, 0), + [308] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_number_literal, 2, 0, 0), + [310] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call, 2, 0, 0), + [312] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call, 2, 0, 0), + [314] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_slice_call, 6, 0, 0), + [316] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_slice_call, 6, 0, 0), + [318] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_cast, 7, 0, 0), + [320] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_cast, 7, 0, 0), + [322] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_tuple_index, 3, 0, 0), + [324] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_tuple_index, 3, 0, 0), + [326] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression_list, 2, 0, 0), + [328] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_expression_list, 2, 0, 0), + [330] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_factor, 2, 0, 0), + [332] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_factor, 2, 0, 0), + [334] = {.entry = {.count = 1, .reusable = true}}, SHIFT(38), + [336] = {.entry = {.count = 1, .reusable = false}}, SHIFT(38), + [338] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_factor_repeat1, 2, 0, 0), + [340] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_factor_repeat1, 2, 0, 0), + [342] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_factor_repeat1, 2, 0, 0), SHIFT_REPEAT(38), + [345] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_factor_repeat1, 2, 0, 0), SHIFT_REPEAT(38), + [348] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_factor, 1, 0, 0), + [350] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_factor, 1, 0, 0), + [352] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary, 2, 0, 0), + [354] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary, 2, 0, 0), + [356] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_unary, 1, 0, 0), + [358] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_unary, 1, 0, 0), + [360] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_term, 1, 0, 0), + [362] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_term, 1, 0, 0), + [364] = {.entry = {.count = 1, .reusable = true}}, SHIFT(37), + [366] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_term, 2, 0, 0), + [368] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_term, 2, 0, 0), + [370] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_term_repeat1, 2, 0, 0), + [372] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_term_repeat1, 2, 0, 0), + [374] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_term_repeat1, 2, 0, 0), SHIFT_REPEAT(37), + [377] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_time_op_statement, 7, 0, 0), + [379] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_time_op_statement, 7, 0, 0), + [381] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_time_op_statement, 9, 0, 0), + [383] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_time_op_statement, 9, 0, 0), + [385] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_return_statement, 3, 0, 0), + [387] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_return_statement, 3, 0, 0), + [389] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_yield_statement, 3, 0, 0), + [391] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_yield_statement, 3, 0, 0), + [393] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_console_statement, 3, 0, 0), + [395] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_console_statement, 3, 0, 0), + [397] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_variable_definition, 3, 0, 1), + [399] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_variable_definition, 3, 0, 1), + [401] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_assign_statement, 4, 0, 6), + [403] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_assign_statement, 4, 0, 6), + [405] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_variable_definition, 4, 0, 3), + [407] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_variable_definition, 4, 0, 3), + [409] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_require_statement, 5, 0, 0), + [411] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_require_statement, 5, 0, 0), + [413] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_for_statement, 9, 0, 0), + [415] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_for_statement, 9, 0, 0), + [417] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_if_statement, 5, 0, 0), + [419] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_if_statement, 5, 0, 0), + [421] = {.entry = {.count = 1, .reusable = true}}, SHIFT(51), + [423] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_block, 1, 0, 0), + [425] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 1, 0, 0), + [427] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_variable_definition, 5, 0, 2), + [429] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_variable_definition, 5, 0, 2), + [431] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_function_call_assignment, 6, 0, 0), + [433] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_function_call_assignment, 6, 0, 0), + [435] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call_assignment, 6, 0, 0), + [437] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call_assignment, 6, 0, 0), + [439] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_block, 2, 0, 0), + [441] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 2, 0, 0), + [443] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_statement, 1, 0, 0), + [445] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_statement, 1, 0, 0), + [447] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_push_statement, 6, 0, 7), + [449] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_push_statement, 6, 0, 7), + [451] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_variable_definition, 6, 0, 4), + [453] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_variable_definition, 6, 0, 4), + [455] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_function_call_assignment, 7, 0, 0), + [457] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_function_call_assignment, 7, 0, 0), + [459] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call_assignment, 7, 0, 0), + [461] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call_assignment, 7, 0, 0), + [463] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_require_statement, 7, 0, 0), + [465] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_require_statement, 7, 0, 0), + [467] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_block, 3, 0, 0), + [469] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_block, 3, 0, 0), + [471] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_if_statement, 7, 0, 0), + [473] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_if_statement, 7, 0, 0), + [475] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_state_function_call_assignment, 8, 0, 0), + [477] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_function_call_assignment, 8, 0, 0), + [479] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_function_call_assignment, 8, 0, 0), + [481] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_call_assignment, 8, 0, 0), + [483] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_tuple_assignment, 8, 0, 0), + [485] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_tuple_assignment, 8, 0, 0), + [487] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_call_statement, 2, 0, 0), + [489] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_call_statement, 2, 0, 0), + [491] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_comparison_repeat1, 2, 0, 0), + [493] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_comparison_repeat1, 2, 0, 0), SHIFT_REPEAT(36), + [496] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_comparison_repeat1, 2, 0, 0), SHIFT_REPEAT(36), + [499] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_comparison_repeat1, 2, 0, 0), + [501] = {.entry = {.count = 1, .reusable = true}}, SHIFT(353), + [503] = {.entry = {.count = 1, .reusable = true}}, SHIFT(362), + [505] = {.entry = {.count = 1, .reusable = true}}, SHIFT(369), + [507] = {.entry = {.count = 1, .reusable = true}}, SHIFT(345), + [509] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_contract_definition_repeat1, 2, 0, 0), + [511] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_contract_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(362), + [514] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_contract_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(369), + [517] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_contract_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(203), + [520] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_comparison, 2, 0, 0), + [522] = {.entry = {.count = 1, .reusable = true}}, SHIFT(36), + [524] = {.entry = {.count = 1, .reusable = false}}, SHIFT(36), + [526] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_comparison, 2, 0, 0), + [528] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_comparison, 1, 0, 0), + [530] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_comparison, 1, 0, 0), + [532] = {.entry = {.count = 1, .reusable = false}}, SHIFT(273), + [534] = {.entry = {.count = 1, .reusable = true}}, SHIFT(332), + [536] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_equality, 1, 0, 0), + [538] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_equality, 1, 0, 0), + [540] = {.entry = {.count = 1, .reusable = true}}, SHIFT(35), + [542] = {.entry = {.count = 1, .reusable = true}}, SHIFT(308), + [544] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_equality, 2, 0, 0), + [546] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_equality, 2, 0, 0), + [548] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_equality_repeat1, 2, 0, 0), + [550] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_equality_repeat1, 2, 0, 0), + [552] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_equality_repeat1, 2, 0, 0), SHIFT_REPEAT(35), + [555] = {.entry = {.count = 1, .reusable = true}}, SHIFT(360), + [557] = {.entry = {.count = 1, .reusable = true}}, SHIFT(322), + [559] = {.entry = {.count = 1, .reusable = true}}, SHIFT(269), + [561] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bit_and, 1, 0, 0), + [563] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_bit_and, 1, 0, 0), + [565] = {.entry = {.count = 1, .reusable = false}}, SHIFT(34), + [567] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_bit_and_repeat1, 2, 0, 0), + [569] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_bit_and_repeat1, 2, 0, 0), + [571] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_bit_and_repeat1, 2, 0, 0), SHIFT_REPEAT(34), + [574] = {.entry = {.count = 1, .reusable = true}}, SHIFT(279), + [576] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bit_and, 2, 0, 0), + [578] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_bit_and, 2, 0, 0), + [580] = {.entry = {.count = 1, .reusable = true}}, SHIFT(280), + [582] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_pragma_value, 1, 0, 0), + [584] = {.entry = {.count = 1, .reusable = true}}, SHIFT(305), + [586] = {.entry = {.count = 1, .reusable = false}}, SHIFT(305), + [588] = {.entry = {.count = 1, .reusable = true}}, SHIFT(180), + [590] = {.entry = {.count = 1, .reusable = true}}, SHIFT(361), + [592] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_definition, 6, 0, 3), + [594] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bit_xor, 2, 0, 0), + [596] = {.entry = {.count = 1, .reusable = true}}, SHIFT(33), + [598] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_bit_xor, 2, 0, 0), + [600] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_definition, 8, 0, 3), + [602] = {.entry = {.count = 1, .reusable = true}}, SHIFT(340), + [604] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_contract_field_definition, 5, 0, 2), + [606] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_definition, 6, 0, 1), + [608] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_definition, 7, 0, 3), + [610] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_constant_definition, 6, 0, 4), + [612] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bit_xor, 1, 0, 0), + [614] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_bit_xor, 1, 0, 0), + [616] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_definition, 7, 0, 1), + [618] = {.entry = {.count = 1, .reusable = true}}, SHIFT(323), + [620] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_function_definition, 5, 0, 1), + [622] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_bit_xor_repeat1, 2, 0, 0), + [624] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_bit_xor_repeat1, 2, 0, 0), SHIFT_REPEAT(33), + [627] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_bit_xor_repeat1, 2, 0, 0), + [629] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_contract_item, 1, 0, 0), + [631] = {.entry = {.count = 1, .reusable = true}}, SHIFT(300), + [633] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_version_constraint, 2, 0, 0), + [635] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_version_constraint, 2, 0, 0), + [637] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_version_constraint, 1, 0, 0), + [639] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_version_constraint, 1, 0, 0), + [641] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bit_or, 1, 0, 0), + [643] = {.entry = {.count = 1, .reusable = false}}, SHIFT(32), + [645] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bit_or, 2, 0, 0), + [647] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_bit_or_repeat1, 2, 0, 0), + [649] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_bit_or_repeat1, 2, 0, 0), SHIFT_REPEAT(32), + [652] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_type_name, 2, 0, 0), + [654] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_type_name, 2, 0, 0), + [656] = {.entry = {.count = 1, .reusable = true}}, SHIFT(209), + [658] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_logical_and, 1, 0, 0), + [660] = {.entry = {.count = 1, .reusable = true}}, SHIFT(31), + [662] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_type_name_repeat1, 2, 0, 0), + [664] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_type_name_repeat1, 2, 0, 0), + [666] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_type_name_repeat1, 2, 0, 0), SHIFT_REPEAT(209), + [669] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_logical_and_repeat1, 2, 0, 0), + [671] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_logical_and_repeat1, 2, 0, 0), SHIFT_REPEAT(31), + [674] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_bit_or_repeat1, 2, 0, 0), + [676] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_type_name, 1, 0, 0), + [678] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_type_name, 1, 0, 0), + [680] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_logical_and, 2, 0, 0), + [682] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_logical_or_repeat1, 2, 0, 0), + [684] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_logical_or_repeat1, 2, 0, 0), SHIFT_REPEAT(30), + [687] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_logical_or, 1, 0, 0), + [689] = {.entry = {.count = 1, .reusable = true}}, SHIFT(30), + [691] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_logical_or, 2, 0, 0), + [693] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_array_suffix, 3, 0, 0), + [695] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array_suffix, 3, 0, 0), + [697] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_array_suffix, 2, 0, 0), + [699] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array_suffix, 2, 0, 0), + [701] = {.entry = {.count = 1, .reusable = true}}, SHIFT(71), + [703] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_base_type, 1, 0, 0), + [705] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_base_type, 1, 0, 0), + [707] = {.entry = {.count = 1, .reusable = true}}, SHIFT(15), + [709] = {.entry = {.count = 1, .reusable = true}}, SHIFT(183), + [711] = {.entry = {.count = 1, .reusable = true}}, SHIFT(292), + [713] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_expression, 1, 0, 0), + [715] = {.entry = {.count = 1, .reusable = false}}, SHIFT(287), + [717] = {.entry = {.count = 1, .reusable = true}}, SHIFT(256), + [719] = {.entry = {.count = 1, .reusable = false}}, SHIFT(234), + [721] = {.entry = {.count = 1, .reusable = true}}, SHIFT(337), + [723] = {.entry = {.count = 1, .reusable = true}}, SHIFT(200), + [725] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_source_file_repeat1, 2, 0, 0), SHIFT_REPEAT(350), + [728] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_source_file_repeat1, 2, 0, 0), + [730] = {.entry = {.count = 1, .reusable = false}}, REDUCE(aux_sym_variable_definition_repeat1, 2, 0, 0), + [732] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_variable_definition_repeat1, 2, 0, 0), SHIFT_REPEAT(256), + [735] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_expression_list_repeat1, 2, 0, 0), SHIFT_REPEAT(23), + [738] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_expression_list_repeat1, 2, 0, 0), + [740] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_console_parameter_list_repeat1, 2, 0, 0), SHIFT_REPEAT(149), + [743] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_console_parameter_list_repeat1, 2, 0, 0), + [745] = {.entry = {.count = 1, .reusable = true}}, SHIFT(43), + [747] = {.entry = {.count = 1, .reusable = true}}, SHIFT(385), + [749] = {.entry = {.count = 1, .reusable = true}}, SHIFT(342), + [751] = {.entry = {.count = 1, .reusable = true}}, SHIFT(351), + [753] = {.entry = {.count = 1, .reusable = true}}, SHIFT(228), + [755] = {.entry = {.count = 1, .reusable = true}}, SHIFT(150), + [757] = {.entry = {.count = 1, .reusable = true}}, SHIFT(154), + [759] = {.entry = {.count = 1, .reusable = true}}, SHIFT(142), + [761] = {.entry = {.count = 1, .reusable = true}}, SHIFT(344), + [763] = {.entry = {.count = 1, .reusable = true}}, SHIFT(166), + [765] = {.entry = {.count = 1, .reusable = true}}, SHIFT(367), + [767] = {.entry = {.count = 1, .reusable = true}}, SHIFT(81), + [769] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_state_object_repeat1, 2, 0, 0), + [771] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_state_object_repeat1, 2, 0, 0), SHIFT_REPEAT(255), + [774] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_parameter_list_repeat1, 2, 0, 0), SHIFT_REPEAT(172), + [777] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_parameter_list_repeat1, 2, 0, 0), + [779] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9), + [781] = {.entry = {.count = 1, .reusable = true}}, SHIFT(326), + [783] = {.entry = {.count = 1, .reusable = true}}, SHIFT(216), + [785] = {.entry = {.count = 1, .reusable = true}}, SHIFT(318), + [787] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_state_function_call_assignment_repeat1, 2, 0, 0), + [789] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_state_function_call_assignment_repeat1, 2, 0, 0), SHIFT_REPEAT(263), + [792] = {.entry = {.count = 1, .reusable = true}}, SHIFT(158), + [794] = {.entry = {.count = 1, .reusable = true}}, SHIFT(317), + [796] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_function_call_assignment_repeat1, 2, 0, 0), SHIFT_REPEAT(163), + [799] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_function_call_assignment_repeat1, 2, 0, 0), + [801] = {.entry = {.count = 1, .reusable = true}}, SHIFT(147), + [803] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_return_type_list_repeat1, 2, 0, 0), SHIFT_REPEAT(181), + [806] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_return_type_list_repeat1, 2, 0, 0), + [808] = {.entry = {.count = 1, .reusable = true}}, SHIFT(112), + [810] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), + [812] = {.entry = {.count = 1, .reusable = true}}, SHIFT(187), + [814] = {.entry = {.count = 1, .reusable = true}}, SHIFT(178), + [816] = {.entry = {.count = 1, .reusable = true}}, SHIFT(364), + [818] = {.entry = {.count = 1, .reusable = true}}, SHIFT(67), + [820] = {.entry = {.count = 1, .reusable = true}}, SHIFT(222), + [822] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6), + [824] = {.entry = {.count = 1, .reusable = true}}, SHIFT(69), + [826] = {.entry = {.count = 1, .reusable = true}}, SHIFT(7), + [828] = {.entry = {.count = 1, .reusable = true}}, SHIFT(75), + [830] = {.entry = {.count = 1, .reusable = true}}, SHIFT(46), + [832] = {.entry = {.count = 1, .reusable = true}}, SHIFT(74), + [834] = {.entry = {.count = 1, .reusable = true}}, SHIFT(236), + [836] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5), + [838] = {.entry = {.count = 1, .reusable = true}}, SHIFT(63), + [840] = {.entry = {.count = 1, .reusable = true}}, SHIFT(151), + [842] = {.entry = {.count = 1, .reusable = true}}, SHIFT(281), + [844] = {.entry = {.count = 1, .reusable = true}}, SHIFT(80), + [846] = {.entry = {.count = 1, .reusable = true}}, SHIFT(24), + [848] = {.entry = {.count = 1, .reusable = true}}, SHIFT(261), + [850] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_entry, 3, 0, 0), + [852] = {.entry = {.count = 1, .reusable = true}}, SHIFT(324), + [854] = {.entry = {.count = 1, .reusable = true}}, SHIFT(250), + [856] = {.entry = {.count = 1, .reusable = true}}, SHIFT(375), + [858] = {.entry = {.count = 1, .reusable = true}}, SHIFT(156), + [860] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_modifier, 1, 0, 0), + [862] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_modifier, 1, 0, 0), + [864] = {.entry = {.count = 1, .reusable = false}}, SHIFT(312), + [866] = {.entry = {.count = 1, .reusable = true}}, SHIFT(311), + [868] = {.entry = {.count = 1, .reusable = true}}, SHIFT(388), + [870] = {.entry = {.count = 1, .reusable = true}}, SHIFT(90), + [872] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_state_typed_binding, 4, 0, 0), + [874] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8), + [876] = {.entry = {.count = 1, .reusable = true}}, SHIFT(77), + [878] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parameter_list, 4, 0, 0), + [880] = {.entry = {.count = 1, .reusable = true}}, SHIFT(144), + [882] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_console_parameter, 1, 0, 0), + [884] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_pragma_directive, 4, 0, 0), + [886] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parameter_list, 5, 0, 0), + [888] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parameter_list, 2, 0, 0), + [890] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parameter_list, 3, 0, 0), + [892] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_parameter, 2, 0, 0), + [894] = {.entry = {.count = 1, .reusable = true}}, SHIFT(114), + [896] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), + [898] = {.entry = {.count = 1, .reusable = true}}, SHIFT(239), + [900] = {.entry = {.count = 1, .reusable = true}}, SHIFT(201), + [902] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_typed_binding, 2, 0, 0), + [904] = {.entry = {.count = 1, .reusable = true}}, SHIFT(277), + [906] = {.entry = {.count = 1, .reusable = true}}, SHIFT(354), + [908] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18), + [910] = {.entry = {.count = 1, .reusable = true}}, SHIFT(179), + [912] = {.entry = {.count = 1, .reusable = true}}, SHIFT(304), + [914] = {.entry = {.count = 1, .reusable = true}}, SHIFT(336), + [916] = {.entry = {.count = 1, .reusable = true}}, SHIFT(119), + [918] = {.entry = {.count = 1, .reusable = true}}, SHIFT(338), + [920] = {.entry = {.count = 1, .reusable = true}}, SHIFT(110), + [922] = {.entry = {.count = 1, .reusable = true}}, SHIFT(282), + [924] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_return_type_list, 5, 0, 0), + [926] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), + [928] = {.entry = {.count = 1, .reusable = true}}, SHIFT(111), + [930] = {.entry = {.count = 1, .reusable = true}}, SHIFT(54), + [932] = {.entry = {.count = 1, .reusable = true}}, SHIFT(21), + [934] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_version_operator, 1, 0, 0), + [936] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), + [938] = {.entry = {.count = 1, .reusable = true}}, SHIFT(50), + [940] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_console_parameter_list, 2, 0, 0), + [942] = {.entry = {.count = 1, .reusable = true}}, SHIFT(275), + [944] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16), + [946] = {.entry = {.count = 1, .reusable = true}}, SHIFT(373), + [948] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), + [950] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), + [952] = {.entry = {.count = 1, .reusable = true}}, SHIFT(356), + [954] = {.entry = {.count = 1, .reusable = true}}, SHIFT(120), + [956] = {.entry = {.count = 1, .reusable = true}}, SHIFT(247), + [958] = {.entry = {.count = 1, .reusable = true}}, SHIFT(274), + [960] = {.entry = {.count = 1, .reusable = true}}, SHIFT(286), + [962] = {.entry = {.count = 1, .reusable = true}}, SHIFT(136), + [964] = {.entry = {.count = 1, .reusable = true}}, SHIFT(121), + [966] = {.entry = {.count = 1, .reusable = true}}, SHIFT(276), + [968] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_return_type_list, 3, 0, 0), + [970] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_require_message, 1, 0, 0), + [972] = {.entry = {.count = 1, .reusable = true}}, SHIFT(352), + [974] = {.entry = {.count = 1, .reusable = true}}, SHIFT(284), + [976] = {.entry = {.count = 1, .reusable = true}}, SHIFT(113), + [978] = {.entry = {.count = 1, .reusable = true}}, SHIFT(278), + [980] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), + [982] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), + [984] = {.entry = {.count = 1, .reusable = true}}, SHIFT(27), + [986] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_console_parameter_list, 4, 0, 0), + [988] = {.entry = {.count = 1, .reusable = true}}, SHIFT(84), + [990] = {.entry = {.count = 1, .reusable = true}}, SHIFT(294), + [992] = {.entry = {.count = 1, .reusable = true}}, SHIFT(25), + [994] = {.entry = {.count = 1, .reusable = true}}, SHIFT(124), + [996] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_array_size, 1, 0, 0), + [998] = {.entry = {.count = 1, .reusable = true}}, SHIFT(29), + [1000] = {.entry = {.count = 1, .reusable = true}}, SHIFT(125), + [1002] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_return_type_list, 6, 0, 0), + [1004] = {.entry = {.count = 1, .reusable = true}}, SHIFT(199), + [1006] = {.entry = {.count = 1, .reusable = true}}, SHIFT(93), + [1008] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_console_parameter_list, 3, 0, 0), + [1010] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_contract_definition, 6, 0, 1), + [1012] = {.entry = {.count = 1, .reusable = true}}, SHIFT(384), + [1014] = {.entry = {.count = 1, .reusable = true}}, SHIFT(126), + [1016] = {.entry = {.count = 1, .reusable = true}}, SHIFT(260), + [1018] = {.entry = {.count = 1, .reusable = true}}, SHIFT(127), + [1020] = {.entry = {.count = 1, .reusable = true}}, SHIFT(159), + [1022] = {.entry = {.count = 1, .reusable = true}}, SHIFT(262), + [1024] = {.entry = {.count = 1, .reusable = true}}, SHIFT(128), + [1026] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_contract_definition, 5, 0, 1), + [1028] = {.entry = {.count = 1, .reusable = true}}, SHIFT(106), + [1030] = {.entry = {.count = 1, .reusable = true}}, SHIFT(313), + [1032] = {.entry = {.count = 1, .reusable = true}}, SHIFT(76), + [1034] = {.entry = {.count = 1, .reusable = true}}, SHIFT(134), + [1036] = {.entry = {.count = 1, .reusable = true}}, SHIFT(167), + [1038] = {.entry = {.count = 1, .reusable = true}}, SHIFT(73), + [1040] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_console_parameter_list, 5, 0, 0), + [1042] = {.entry = {.count = 1, .reusable = true}}, SHIFT(264), + [1044] = {.entry = {.count = 1, .reusable = true}}, SHIFT(299), + [1046] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 2, 0, 0), + [1048] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_return_type_list, 4, 0, 0), + [1050] = {.entry = {.count = 1, .reusable = true}}, SHIFT(170), + [1052] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_tx_var, 1, 0, 0), + [1054] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), + [1056] = {.entry = {.count = 1, .reusable = true}}, SHIFT(131), + [1058] = {.entry = {.count = 1, .reusable = true}}, SHIFT(254), + [1060] = {.entry = {.count = 1, .reusable = true}}, SHIFT(132), + [1062] = {.entry = {.count = 1, .reusable = true}}, SHIFT(79), + [1064] = {.entry = {.count = 1, .reusable = true}}, SHIFT(380), + [1066] = {.entry = {.count = 1, .reusable = true}}, SHIFT(13), + [1068] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), + [1070] = {.entry = {.count = 1, .reusable = true}}, SHIFT(115), + [1072] = {.entry = {.count = 1, .reusable = true}}, SHIFT(52), + [1074] = {.entry = {.count = 1, .reusable = true}}, SHIFT(133), + [1076] = {.entry = {.count = 1, .reusable = true}}, SHIFT(290), + [1078] = {.entry = {.count = 1, .reusable = true}}, SHIFT(109), + [1080] = {.entry = {.count = 1, .reusable = true}}, SHIFT(107), + [1082] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_pragma_value, 2, 0, 0), + [1084] = {.entry = {.count = 1, .reusable = true}}, SHIFT(14), + [1086] = {.entry = {.count = 1, .reusable = true}}, SHIFT(283), + [1088] = {.entry = {.count = 1, .reusable = true}}, SHIFT(359), + [1090] = {.entry = {.count = 1, .reusable = true}}, SHIFT(174), + [1092] = {.entry = {.count = 1, .reusable = true}}, SHIFT(95), + [1094] = {.entry = {.count = 1, .reusable = true}}, SHIFT(45), + [1096] = {.entry = {.count = 1, .reusable = true}}, SHIFT(94), +}; + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef TREE_SITTER_HIDE_SYMBOLS +#define TS_PUBLIC +#elif defined(_WIN32) +#define TS_PUBLIC __declspec(dllexport) +#else +#define TS_PUBLIC __attribute__((visibility("default"))) +#endif + +TS_PUBLIC const TSLanguage *tree_sitter_silverscript(void) { + static const TSLanguage language = { + .abi_version = LANGUAGE_VERSION, + .symbol_count = SYMBOL_COUNT, + .alias_count = ALIAS_COUNT, + .token_count = TOKEN_COUNT, + .external_token_count = EXTERNAL_TOKEN_COUNT, + .state_count = STATE_COUNT, + .large_state_count = LARGE_STATE_COUNT, + .production_id_count = PRODUCTION_ID_COUNT, + .supertype_count = SUPERTYPE_COUNT, + .field_count = FIELD_COUNT, + .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, + .parse_table = &ts_parse_table[0][0], + .small_parse_table = ts_small_parse_table, + .small_parse_table_map = ts_small_parse_table_map, + .parse_actions = ts_parse_actions, + .symbol_names = ts_symbol_names, + .field_names = ts_field_names, + .field_map_slices = ts_field_map_slices, + .field_map_entries = ts_field_map_entries, + .symbol_metadata = ts_symbol_metadata, + .public_symbol_map = ts_symbol_map, + .alias_map = ts_non_terminal_alias_map, + .alias_sequences = &ts_alias_sequences[0][0], + .lex_modes = (const void*)ts_lex_modes, + .lex_fn = ts_lex, + .keyword_lex_fn = ts_lex_keywords, + .keyword_capture_token = sym_identifier, + .primary_state_ids = ts_primary_state_ids, + .name = "silverscript", + .max_reserved_word_set_size = 0, + .metadata = { + .major_version = 0, + .minor_version = 1, + .patch_version = 0, + }, + }; + return &language; +} +#ifdef __cplusplus +} +#endif diff --git a/tree-sitter/src/tree_sitter/alloc.h b/tree-sitter/src/tree_sitter/alloc.h new file mode 100644 index 00000000..1abdd120 --- /dev/null +++ b/tree-sitter/src/tree_sitter/alloc.h @@ -0,0 +1,54 @@ +#ifndef TREE_SITTER_ALLOC_H_ +#define TREE_SITTER_ALLOC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +// Allow clients to override allocation functions +#ifdef TREE_SITTER_REUSE_ALLOCATOR + +extern void *(*ts_current_malloc)(size_t size); +extern void *(*ts_current_calloc)(size_t count, size_t size); +extern void *(*ts_current_realloc)(void *ptr, size_t size); +extern void (*ts_current_free)(void *ptr); + +#ifndef ts_malloc +#define ts_malloc ts_current_malloc +#endif +#ifndef ts_calloc +#define ts_calloc ts_current_calloc +#endif +#ifndef ts_realloc +#define ts_realloc ts_current_realloc +#endif +#ifndef ts_free +#define ts_free ts_current_free +#endif + +#else + +#ifndef ts_malloc +#define ts_malloc malloc +#endif +#ifndef ts_calloc +#define ts_calloc calloc +#endif +#ifndef ts_realloc +#define ts_realloc realloc +#endif +#ifndef ts_free +#define ts_free free +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_ALLOC_H_ diff --git a/tree-sitter/src/tree_sitter/array.h b/tree-sitter/src/tree_sitter/array.h new file mode 100644 index 00000000..e99918e5 --- /dev/null +++ b/tree-sitter/src/tree_sitter/array.h @@ -0,0 +1,347 @@ +#ifndef TREE_SITTER_ARRAY_H_ +#define TREE_SITTER_ARRAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./alloc.h" + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4101) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +#define Array(T) \ + struct { \ + T *contents; \ + uint32_t size; \ + uint32_t capacity; \ + } + +/// Initialize an array. +#define array_init(self) \ + ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) + +/// Create an empty array. +#define array_new() \ + { NULL, 0, 0 } + +/// Get a pointer to the element at a given `index` in the array. +#define array_get(self, _index) \ + (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) + +/// Get a pointer to the first element in the array. +#define array_front(self) array_get(self, 0) + +/// Get a pointer to the last element in the array. +#define array_back(self) array_get(self, (self)->size - 1) + +/// Clear the array, setting its size to zero. Note that this does not free any +/// memory allocated for the array's contents. +#define array_clear(self) ((self)->size = 0) + +/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is +/// less than the array's current capacity, this function has no effect. +#define array_reserve(self, new_capacity) \ + ((self)->contents = _array__reserve( \ + (void *)(self)->contents, &(self)->capacity, \ + array_elem_size(self), new_capacity) \ + ) + +/// Free any memory allocated for this array. Note that this does not free any +/// memory allocated for the array's contents. +#define array_delete(self) _array__delete((self), (void *)(self)->contents, sizeof(*self)) + +/// Push a new `element` onto the end of the array. +#define array_push(self, element) \ + do { \ + (self)->contents = _array__grow( \ + (void *)(self)->contents, (self)->size, &(self)->capacity, \ + 1, array_elem_size(self) \ + ); \ + (self)->contents[(self)->size++] = (element); \ + } while(0) + +/// Increase the array's size by `count` elements. +/// New elements are zero-initialized. +#define array_grow_by(self, count) \ + do { \ + if ((count) == 0) break; \ + (self)->contents = _array__grow( \ + (self)->contents, (self)->size, &(self)->capacity, \ + count, array_elem_size(self) \ + ); \ + memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ + (self)->size += (count); \ + } while (0) + +/// Append all elements from one array to the end of another. +#define array_push_all(self, other) \ + array_extend((self), (other)->size, (other)->contents) + +/// Append `count` elements to the end of the array, reading their values from the +/// `contents` pointer. +#define array_extend(self, count, other_contents) \ + (self)->contents = _array__splice( \ + (void*)(self)->contents, &(self)->size, &(self)->capacity, \ + array_elem_size(self), (self)->size, 0, count, other_contents \ + ) + +/// Remove `old_count` elements from the array starting at the given `index`. At +/// the same index, insert `new_count` new elements, reading their values from the +/// `new_contents` pointer. +#define array_splice(self, _index, old_count, new_count, new_contents) \ + (self)->contents = _array__splice( \ + (void *)(self)->contents, &(self)->size, &(self)->capacity, \ + array_elem_size(self), _index, old_count, new_count, new_contents \ + ) + +/// Insert one `element` into the array at the given `index`. +#define array_insert(self, _index, element) \ + (self)->contents = _array__splice( \ + (void *)(self)->contents, &(self)->size, &(self)->capacity, \ + array_elem_size(self), _index, 0, 1, &(element) \ + ) + +/// Remove one element from the array at the given `index`. +#define array_erase(self, _index) \ + _array__erase((void *)(self)->contents, &(self)->size, array_elem_size(self), _index) + +/// Pop the last element off the array, returning the element by value. +#define array_pop(self) ((self)->contents[--(self)->size]) + +/// Assign the contents of one array to another, reallocating if necessary. +#define array_assign(self, other) \ + (self)->contents = _array__assign( \ + (void *)(self)->contents, &(self)->size, &(self)->capacity, \ + (const void *)(other)->contents, (other)->size, array_elem_size(self) \ + ) + +/// Swap one array with another +#define array_swap(self, other) \ + do { \ + struct Swap swapped_contents = _array__swap( \ + (void *)(self)->contents, &(self)->size, &(self)->capacity, \ + (void *)(other)->contents, &(other)->size, &(other)->capacity \ + ); \ + (self)->contents = swapped_contents.self_contents; \ + (other)->contents = swapped_contents.other_contents; \ + } while (0) + +/// Get the size of the array contents +#define array_elem_size(self) (sizeof *(self)->contents) + +/// Search a sorted array for a given `needle` value, using the given `compare` +/// callback to determine the order. +/// +/// If an existing element is found to be equal to `needle`, then the `index` +/// out-parameter is set to the existing value's index, and the `exists` +/// out-parameter is set to true. Otherwise, `index` is set to an index where +/// `needle` should be inserted in order to preserve the sorting, and `exists` +/// is set to false. +#define array_search_sorted_with(self, compare, needle, _index, _exists) \ + _array__search_sorted(self, 0, compare, , needle, _index, _exists) + +/// Search a sorted array for a given `needle` value, using integer comparisons +/// of a given struct field (specified with a leading dot) to determine the order. +/// +/// See also `array_search_sorted_with`. +#define array_search_sorted_by(self, field, needle, _index, _exists) \ + _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) + +/// Insert a given `value` into a sorted array, using the given `compare` +/// callback to determine the order. +#define array_insert_sorted_with(self, compare, value) \ + do { \ + unsigned _index, _exists; \ + array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ + if (!_exists) array_insert(self, _index, value); \ + } while (0) + +/// Insert a given `value` into a sorted array, using integer comparisons of +/// a given struct field (specified with a leading dot) to determine the order. +/// +/// See also `array_search_sorted_by`. +#define array_insert_sorted_by(self, field, value) \ + do { \ + unsigned _index, _exists; \ + array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ + if (!_exists) array_insert(self, _index, value); \ + } while (0) + +// Private + +// Pointers to individual `Array` fields (rather than the entire `Array` itself) +// are passed to the various `_array__*` functions below to address strict aliasing +// violations that arises when the _entire_ `Array` struct is passed as `Array(void)*`. +// +// The `Array` type itself was not altered as a solution in order to avoid breakage +// with existing consumers (in particular, parsers with external scanners). + +/// This is not what you're looking for, see `array_delete`. +static inline void _array__delete(void *self, void *contents, size_t self_size) { + if (contents) ts_free(contents); + if (self) memset(self, 0, self_size); +} + +/// This is not what you're looking for, see `array_erase`. +static inline void _array__erase(void* self_contents, uint32_t *size, + size_t element_size, uint32_t index) { + assert(index < *size); + char *contents = (char *)self_contents; + memmove(contents + index * element_size, contents + (index + 1) * element_size, + (*size - index - 1) * element_size); + (*size)--; +} + +/// This is not what you're looking for, see `array_reserve`. +static inline void *_array__reserve(void *contents, uint32_t *capacity, + size_t element_size, uint32_t new_capacity) { + void *new_contents = contents; + if (new_capacity > *capacity) { + if (contents) { + new_contents = ts_realloc(contents, new_capacity * element_size); + } else { + new_contents = ts_malloc(new_capacity * element_size); + } + *capacity = new_capacity; + } + return new_contents; +} + +/// This is not what you're looking for, see `array_assign`. +static inline void *_array__assign(void* self_contents, uint32_t *self_size, uint32_t *self_capacity, + const void *other_contents, uint32_t other_size, size_t element_size) { + void *new_contents = _array__reserve(self_contents, self_capacity, element_size, other_size); + *self_size = other_size; + memcpy(new_contents, other_contents, *self_size * element_size); + return new_contents; +} + +struct Swap { + void *self_contents; + void *other_contents; +}; + +/// This is not what you're looking for, see `array_swap`. +// static inline void _array__swap(Array *self, Array *other) { +static inline struct Swap _array__swap(void *self_contents, uint32_t *self_size, uint32_t *self_capacity, + void *other_contents, uint32_t *other_size, uint32_t *other_capacity) { + void *new_self_contents = other_contents; + uint32_t new_self_size = *other_size; + uint32_t new_self_capacity = *other_capacity; + + void *new_other_contents = self_contents; + *other_size = *self_size; + *other_capacity = *self_capacity; + + *self_size = new_self_size; + *self_capacity = new_self_capacity; + + struct Swap out = { + .self_contents = new_self_contents, + .other_contents = new_other_contents, + }; + return out; +} + +/// This is not what you're looking for, see `array_push` or `array_grow_by`. +static inline void *_array__grow(void *contents, uint32_t size, uint32_t *capacity, + uint32_t count, size_t element_size) { + void *new_contents = contents; + uint32_t new_size = size + count; + if (new_size > *capacity) { + uint32_t new_capacity = *capacity * 2; + if (new_capacity < 8) new_capacity = 8; + if (new_capacity < new_size) new_capacity = new_size; + new_contents = _array__reserve(contents, capacity, element_size, new_capacity); + } + return new_contents; +} + +/// This is not what you're looking for, see `array_splice`. +static inline void *_array__splice(void *self_contents, uint32_t *size, uint32_t *capacity, + size_t element_size, + uint32_t index, uint32_t old_count, + uint32_t new_count, const void *elements) { + uint32_t new_size = *size + new_count - old_count; + uint32_t old_end = index + old_count; + uint32_t new_end = index + new_count; + assert(old_end <= *size); + + void *new_contents = _array__reserve(self_contents, capacity, element_size, new_size); + + char *contents = (char *)new_contents; + if (*size > old_end) { + memmove( + contents + new_end * element_size, + contents + old_end * element_size, + (*size - old_end) * element_size + ); + } + if (new_count > 0) { + if (elements) { + memcpy( + (contents + index * element_size), + elements, + new_count * element_size + ); + } else { + memset( + (contents + index * element_size), + 0, + new_count * element_size + ); + } + } + *size += new_count - old_count; + + return new_contents; +} + +/// A binary search routine, based on Rust's `std::slice::binary_search_by`. +/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. +#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ + do { \ + *(_index) = start; \ + *(_exists) = false; \ + uint32_t size = (self)->size - *(_index); \ + if (size == 0) break; \ + int comparison; \ + while (size > 1) { \ + uint32_t half_size = size / 2; \ + uint32_t mid_index = *(_index) + half_size; \ + comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ + if (comparison <= 0) *(_index) = mid_index; \ + size -= half_size; \ + } \ + comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ + if (comparison == 0) *(_exists) = true; \ + else if (comparison < 0) *(_index) += 1; \ + } while (0) + +/// Helper macro for the `_sorted_by` routines below. This takes the left (existing) +/// parameter by reference in order to work with the generic sorting function above. +#define _compare_int(a, b) ((int)*(a) - (int)(b)) + +#ifdef _MSC_VER +#pragma warning(pop) +#elif defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_ARRAY_H_ diff --git a/tree-sitter/src/tree_sitter/parser.h b/tree-sitter/src/tree_sitter/parser.h new file mode 100644 index 00000000..858107de --- /dev/null +++ b/tree-sitter/src/tree_sitter/parser.h @@ -0,0 +1,286 @@ +#ifndef TREE_SITTER_PARSER_H_ +#define TREE_SITTER_PARSER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define ts_builtin_sym_error ((TSSymbol)-1) +#define ts_builtin_sym_end 0 +#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 + +#ifndef TREE_SITTER_API_H_ +typedef uint16_t TSStateId; +typedef uint16_t TSSymbol; +typedef uint16_t TSFieldId; +typedef struct TSLanguage TSLanguage; +typedef struct TSLanguageMetadata { + uint8_t major_version; + uint8_t minor_version; + uint8_t patch_version; +} TSLanguageMetadata; +#endif + +typedef struct { + TSFieldId field_id; + uint8_t child_index; + bool inherited; +} TSFieldMapEntry; + +// Used to index the field and supertype maps. +typedef struct { + uint16_t index; + uint16_t length; +} TSMapSlice; + +typedef struct { + bool visible; + bool named; + bool supertype; +} TSSymbolMetadata; + +typedef struct TSLexer TSLexer; + +struct TSLexer { + int32_t lookahead; + TSSymbol result_symbol; + void (*advance)(TSLexer *, bool); + void (*mark_end)(TSLexer *); + uint32_t (*get_column)(TSLexer *); + bool (*is_at_included_range_start)(const TSLexer *); + bool (*eof)(const TSLexer *); + void (*log)(const TSLexer *, const char *, ...); +}; + +typedef enum { + TSParseActionTypeShift, + TSParseActionTypeReduce, + TSParseActionTypeAccept, + TSParseActionTypeRecover, +} TSParseActionType; + +typedef union { + struct { + uint8_t type; + TSStateId state; + bool extra; + bool repetition; + } shift; + struct { + uint8_t type; + uint8_t child_count; + TSSymbol symbol; + int16_t dynamic_precedence; + uint16_t production_id; + } reduce; + uint8_t type; +} TSParseAction; + +typedef struct { + uint16_t lex_state; + uint16_t external_lex_state; +} TSLexMode; + +typedef struct { + uint16_t lex_state; + uint16_t external_lex_state; + uint16_t reserved_word_set_id; +} TSLexerMode; + +typedef union { + TSParseAction action; + struct { + uint8_t count; + bool reusable; + } entry; +} TSParseActionEntry; + +typedef struct { + int32_t start; + int32_t end; +} TSCharacterRange; + +struct TSLanguage { + uint32_t abi_version; + uint32_t symbol_count; + uint32_t alias_count; + uint32_t token_count; + uint32_t external_token_count; + uint32_t state_count; + uint32_t large_state_count; + uint32_t production_id_count; + uint32_t field_count; + uint16_t max_alias_sequence_length; + const uint16_t *parse_table; + const uint16_t *small_parse_table; + const uint32_t *small_parse_table_map; + const TSParseActionEntry *parse_actions; + const char * const *symbol_names; + const char * const *field_names; + const TSMapSlice *field_map_slices; + const TSFieldMapEntry *field_map_entries; + const TSSymbolMetadata *symbol_metadata; + const TSSymbol *public_symbol_map; + const uint16_t *alias_map; + const TSSymbol *alias_sequences; + const TSLexerMode *lex_modes; + bool (*lex_fn)(TSLexer *, TSStateId); + bool (*keyword_lex_fn)(TSLexer *, TSStateId); + TSSymbol keyword_capture_token; + struct { + const bool *states; + const TSSymbol *symbol_map; + void *(*create)(void); + void (*destroy)(void *); + bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); + unsigned (*serialize)(void *, char *); + void (*deserialize)(void *, const char *, unsigned); + } external_scanner; + const TSStateId *primary_state_ids; + const char *name; + const TSSymbol *reserved_words; + uint16_t max_reserved_word_set_size; + uint32_t supertype_count; + const TSSymbol *supertype_symbols; + const TSMapSlice *supertype_map_slices; + const TSSymbol *supertype_map_entries; + TSLanguageMetadata metadata; +}; + +static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { + uint32_t index = 0; + uint32_t size = len - index; + while (size > 1) { + uint32_t half_size = size / 2; + uint32_t mid_index = index + half_size; + const TSCharacterRange *range = &ranges[mid_index]; + if (lookahead >= range->start && lookahead <= range->end) { + return true; + } else if (lookahead > range->end) { + index = mid_index; + } + size -= half_size; + } + const TSCharacterRange *range = &ranges[index]; + return (lookahead >= range->start && lookahead <= range->end); +} + +/* + * Lexer Macros + */ + +#ifdef _MSC_VER +#define UNUSED __pragma(warning(suppress : 4101)) +#else +#define UNUSED __attribute__((unused)) +#endif + +#define START_LEXER() \ + bool result = false; \ + bool skip = false; \ + UNUSED \ + bool eof = false; \ + int32_t lookahead; \ + goto start; \ + next_state: \ + lexer->advance(lexer, skip); \ + start: \ + skip = false; \ + lookahead = lexer->lookahead; + +#define ADVANCE(state_value) \ + { \ + state = state_value; \ + goto next_state; \ + } + +#define ADVANCE_MAP(...) \ + { \ + static const uint16_t map[] = { __VA_ARGS__ }; \ + for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ + if (map[i] == lookahead) { \ + state = map[i + 1]; \ + goto next_state; \ + } \ + } \ + } + +#define SKIP(state_value) \ + { \ + skip = true; \ + state = state_value; \ + goto next_state; \ + } + +#define ACCEPT_TOKEN(symbol_value) \ + result = true; \ + lexer->result_symbol = symbol_value; \ + lexer->mark_end(lexer); + +#define END_STATE() return result; + +/* + * Parse Table Macros + */ + +#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) + +#define STATE(id) id + +#define ACTIONS(id) id + +#define SHIFT(state_value) \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .state = (state_value) \ + } \ + }} + +#define SHIFT_REPEAT(state_value) \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .state = (state_value), \ + .repetition = true \ + } \ + }} + +#define SHIFT_EXTRA() \ + {{ \ + .shift = { \ + .type = TSParseActionTypeShift, \ + .extra = true \ + } \ + }} + +#define REDUCE(symbol_name, children, precedence, prod_id) \ + {{ \ + .reduce = { \ + .type = TSParseActionTypeReduce, \ + .symbol = symbol_name, \ + .child_count = children, \ + .dynamic_precedence = precedence, \ + .production_id = prod_id \ + }, \ + }} + +#define RECOVER() \ + {{ \ + .type = TSParseActionTypeRecover \ + }} + +#define ACCEPT_INPUT() \ + {{ \ + .type = TSParseActionTypeAccept \ + }} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_SITTER_PARSER_H_ diff --git a/tree-sitter/tests/examples_parse_smoke_test.rs b/tree-sitter/tests/examples_parse_smoke_test.rs new file mode 100644 index 00000000..e14f88bc --- /dev/null +++ b/tree-sitter/tests/examples_parse_smoke_test.rs @@ -0,0 +1,50 @@ +use std::fs; +use std::path::{Path, PathBuf}; + +use tree_sitter::Parser; + +fn examples_dir() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("..").join("silverscript-lang").join("tests").join("examples") +} + +#[test] +// note: tree-sitter parse "my-file.sil" produces more descriptive outputs when errored but is heavier to run +fn parses_all_examples_without_errors() { + let examples_dir = examples_dir(); + assert!(examples_dir.is_dir(), "examples directory not found: {}", examples_dir.display()); + + let mut example_files = fs::read_dir(&examples_dir) + .expect("failed to read examples directory") + .filter_map(Result::ok) + .map(|entry| entry.path()) + .filter(|path| path.extension().and_then(|ext| ext.to_str()) == Some("sil")) + .collect::>(); + + example_files.sort(); + assert!(!example_files.is_empty(), "no .sil files found in {}", examples_dir.display()); + + let mut parser = Parser::new(); + parser.set_language(&tree_sitter_silverscript::LANGUAGE.into()).expect("failed to load tree-sitter-silverscript grammar"); + + let mut failures = Vec::new(); + + for file in example_files { + let source = match fs::read_to_string(&file) { + Ok(source) => source, + Err(err) => { + panic!("{}: failed to read ({err})", file.display()); + } + }; + + let Some(tree) = parser.parse(&source, None) else { + failures.push(format!("{}: parser returned no tree", file.display())); + continue; + }; + + if tree.root_node().has_error() { + failures.push(format!("{}: parse tree contains syntax errors", file.display())); + } + } + + assert!(failures.is_empty(), "{} example file(s) failed to parse:\n{}", failures.len(), failures.join("\n")); +} diff --git a/tree-sitter/tree-sitter.json b/tree-sitter/tree-sitter.json new file mode 100644 index 00000000..35d75423 --- /dev/null +++ b/tree-sitter/tree-sitter.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json", + "grammars": [ + { + "name": "silverscript", + "camelcase": "SilverScript", + "title": "SilverScript", + "scope": "source.silverscript", + "file-types": ["sil"], + "injection-regex": "^silverscript$", + "class-name": "TreeSitterSilverscript" + } + ], + "metadata": { + "version": "0.1.0", + "license": "ISC", + "description": "Kaspa SilverScript Lang", + "authors": [ + { + "name": "Kaspa Developers" + } + ], + "links": { + "repository": "https://github.com/tree-sitter/tree-sitter-silverscript" + } + }, + "bindings": { + "c": true, + "go": true, + "java": false, + "node": true, + "python": true, + "rust": true, + "swift": true, + "zig": false + } +}