1use std::{
2 collections::{BTreeMap, BTreeSet},
3 error::Error,
4 fmt,
5};
6
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 AssignmentOp, BinaryOp, BlockStmt, BuiltinType, BuiltinValue, CompilerErrorCode, Expr,
11 ExprKind, FunctionDecl, LangSpec, Literal, MagicLiteral, Script, Stmt, TopLevelItem, TypeKind,
12 TypeSpec, UnaryOp, nwscript_string_hash,
13};
14
15#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticOptions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SemanticOptions", "require_entrypoint", &self.require_entrypoint,
"allow_conditional_script", &&self.allow_conditional_script)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticOptions {
#[inline]
fn clone(&self) -> SemanticOptions {
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SemanticOptions { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticOptions {
#[inline]
fn eq(&self, other: &SemanticOptions) -> bool {
self.require_entrypoint == other.require_entrypoint &&
self.allow_conditional_script == other.allow_conditional_script
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SemanticOptions {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for SemanticOptions {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.require_entrypoint, state);
::core::hash::Hash::hash(&self.allow_conditional_script, state)
}
}Hash, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticOptions {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticOptions", false as usize + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"require_entrypoint", &self.require_entrypoint)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"allow_conditional_script",
&self.allow_conditional_script)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticOptions {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"require_entrypoint" =>
_serde::__private228::Ok(__Field::__field0),
"allow_conditional_script" =>
_serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"require_entrypoint" =>
_serde::__private228::Ok(__Field::__field0),
b"allow_conditional_script" =>
_serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticOptions>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticOptions;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticOptions")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticOptions with 2 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticOptions with 2 elements")),
};
_serde::__private228::Ok(SemanticOptions {
require_entrypoint: __field0,
allow_conditional_script: __field1,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<bool> =
_serde::__private228::None;
let mut __field1: _serde::__private228::Option<bool> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("require_entrypoint"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("allow_conditional_script"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("require_entrypoint")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("allow_conditional_script")?,
};
_serde::__private228::Ok(SemanticOptions {
require_entrypoint: __field0,
allow_conditional_script: __field1,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["require_entrypoint", "allow_conditional_script"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticOptions", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticOptions>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize, #[automatically_derived]
impl ::core::default::Default for SemanticOptions {
#[inline]
fn default() -> SemanticOptions {
SemanticOptions {
require_entrypoint: ::core::default::Default::default(),
allow_conditional_script: ::core::default::Default::default(),
}
}
}Default)]
17pub struct SemanticOptions {
18 pub require_entrypoint: bool,
20 pub allow_conditional_script: bool,
23}
24
25#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "SemanticError",
"code", &self.code, "span", &self.span, "message", &&self.message)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticError {
#[inline]
fn clone(&self) -> SemanticError {
SemanticError {
code: ::core::clone::Clone::clone(&self.code),
span: ::core::clone::Clone::clone(&self.span),
message: ::core::clone::Clone::clone(&self.message),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticError {
#[inline]
fn eq(&self, other: &SemanticError) -> bool {
self.code == other.code && self.span == other.span &&
self.message == other.message
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SemanticError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<CompilerErrorCode>;
let _: ::core::cmp::AssertParamIsEq<crate::Span>;
let _: ::core::cmp::AssertParamIsEq<String>;
}
}Eq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticError {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticError", false as usize + 1 + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"code", &self.code)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"span", &self.span)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"message", &self.message)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticError {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __field2, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"code" => _serde::__private228::Ok(__Field::__field0),
"span" => _serde::__private228::Ok(__Field::__field1),
"message" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"code" => _serde::__private228::Ok(__Field::__field0),
b"span" => _serde::__private228::Ok(__Field::__field1),
b"message" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticError>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticError;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticError")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<CompilerErrorCode>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticError with 3 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<crate::Span>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticError with 3 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct SemanticError with 3 elements")),
};
_serde::__private228::Ok(SemanticError {
code: __field0,
span: __field1,
message: __field2,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0:
_serde::__private228::Option<CompilerErrorCode> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<crate::Span> =
_serde::__private228::None;
let mut __field2: _serde::__private228::Option<String> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("code"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<CompilerErrorCode>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("span"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<crate::Span>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("message"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("code")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("span")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("message")?,
};
_serde::__private228::Ok(SemanticError {
code: __field0,
span: __field1,
message: __field2,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["code", "span", "message"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticError", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticError>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
28pub struct SemanticError {
29 pub code: CompilerErrorCode,
31 pub span: crate::Span,
33 pub message: String,
35}
36
37impl SemanticError {
38 fn new(code: CompilerErrorCode, span: crate::Span, message: impl Into<String>) -> Self {
39 Self {
40 code,
41 span,
42 message: message.into(),
43 }
44 }
45}
46
47impl fmt::Display for SemanticError {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 f.write_fmt(format_args!("{0} ({1})", self.message, self.code.code()))write!(f, "{} ({})", self.message, self.code.code())
50 }
51}
52
53impl Error for SemanticError {}
54
55#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticType {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
SemanticType::Void =>
::core::fmt::Formatter::write_str(f, "Void"),
SemanticType::Int => ::core::fmt::Formatter::write_str(f, "Int"),
SemanticType::Float =>
::core::fmt::Formatter::write_str(f, "Float"),
SemanticType::String =>
::core::fmt::Formatter::write_str(f, "String"),
SemanticType::Object =>
::core::fmt::Formatter::write_str(f, "Object"),
SemanticType::Action =>
::core::fmt::Formatter::write_str(f, "Action"),
SemanticType::Vector =>
::core::fmt::Formatter::write_str(f, "Vector"),
SemanticType::Struct(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Struct",
&__self_0),
SemanticType::EngineStructure(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"EngineStructure", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticType {
#[inline]
fn clone(&self) -> SemanticType {
match self {
SemanticType::Void => SemanticType::Void,
SemanticType::Int => SemanticType::Int,
SemanticType::Float => SemanticType::Float,
SemanticType::String => SemanticType::String,
SemanticType::Object => SemanticType::Object,
SemanticType::Action => SemanticType::Action,
SemanticType::Vector => SemanticType::Vector,
SemanticType::Struct(__self_0) =>
SemanticType::Struct(::core::clone::Clone::clone(__self_0)),
SemanticType::EngineStructure(__self_0) =>
SemanticType::EngineStructure(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticType {
#[inline]
fn eq(&self, other: &SemanticType) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(SemanticType::Struct(__self_0),
SemanticType::Struct(__arg1_0)) => __self_0 == __arg1_0,
(SemanticType::EngineStructure(__self_0),
SemanticType::EngineStructure(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SemanticType {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for SemanticType {
#[inline]
fn partial_cmp(&self, other: &SemanticType)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(SemanticType::Struct(__self_0), SemanticType::Struct(__arg1_0))
=> ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(SemanticType::EngineStructure(__self_0),
SemanticType::EngineStructure(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for SemanticType {
#[inline]
fn cmp(&self, other: &SemanticType) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(SemanticType::Struct(__self_0),
SemanticType::Struct(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(SemanticType::EngineStructure(__self_0),
SemanticType::EngineStructure(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => ::core::cmp::Ordering::Equal,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::hash::Hash for SemanticType {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
SemanticType::Struct(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
SemanticType::EngineStructure(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticType {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
match *self {
SemanticType::Void =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 0u32, "Void"),
SemanticType::Int =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 1u32, "Int"),
SemanticType::Float =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 2u32, "Float"),
SemanticType::String =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 3u32, "String"),
SemanticType::Object =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 4u32, "Object"),
SemanticType::Action =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 5u32, "Action"),
SemanticType::Vector =>
_serde::Serializer::serialize_unit_variant(__serializer,
"SemanticType", 6u32, "Vector"),
SemanticType::Struct(ref __field0) =>
_serde::Serializer::serialize_newtype_variant(__serializer,
"SemanticType", 7u32, "Struct", __field0),
SemanticType::EngineStructure(ref __field0) =>
_serde::Serializer::serialize_newtype_variant(__serializer,
"SemanticType", 8u32, "EngineStructure", __field0),
}
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticType {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
__field4,
__field5,
__field6,
__field7,
__field8,
}
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"variant identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
3u64 => _serde::__private228::Ok(__Field::__field3),
4u64 => _serde::__private228::Ok(__Field::__field4),
5u64 => _serde::__private228::Ok(__Field::__field5),
6u64 => _serde::__private228::Ok(__Field::__field6),
7u64 => _serde::__private228::Ok(__Field::__field7),
8u64 => _serde::__private228::Ok(__Field::__field8),
_ =>
_serde::__private228::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 9")),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"Void" => _serde::__private228::Ok(__Field::__field0),
"Int" => _serde::__private228::Ok(__Field::__field1),
"Float" => _serde::__private228::Ok(__Field::__field2),
"String" => _serde::__private228::Ok(__Field::__field3),
"Object" => _serde::__private228::Ok(__Field::__field4),
"Action" => _serde::__private228::Ok(__Field::__field5),
"Vector" => _serde::__private228::Ok(__Field::__field6),
"Struct" => _serde::__private228::Ok(__Field::__field7),
"EngineStructure" =>
_serde::__private228::Ok(__Field::__field8),
_ => {
_serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
VARIANTS))
}
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"Void" => _serde::__private228::Ok(__Field::__field0),
b"Int" => _serde::__private228::Ok(__Field::__field1),
b"Float" => _serde::__private228::Ok(__Field::__field2),
b"String" => _serde::__private228::Ok(__Field::__field3),
b"Object" => _serde::__private228::Ok(__Field::__field4),
b"Action" => _serde::__private228::Ok(__Field::__field5),
b"Vector" => _serde::__private228::Ok(__Field::__field6),
b"Struct" => _serde::__private228::Ok(__Field::__field7),
b"EngineStructure" =>
_serde::__private228::Ok(__Field::__field8),
_ => {
let __value =
&_serde::__private228::from_utf8_lossy(__value);
_serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
VARIANTS))
}
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticType>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticType;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"enum SemanticType")
}
fn visit_enum<__A>(self, __data: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::EnumAccess<'de> {
match _serde::de::EnumAccess::variant(__data)? {
(__Field::__field0, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::Void)
}
(__Field::__field1, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::Int)
}
(__Field::__field2, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::Float)
}
(__Field::__field3, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::String)
}
(__Field::__field4, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::Object)
}
(__Field::__field5, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::Action)
}
(__Field::__field6, __variant) => {
_serde::de::VariantAccess::unit_variant(__variant)?;
_serde::__private228::Ok(SemanticType::Vector)
}
(__Field::__field7, __variant) =>
_serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<String>(__variant),
SemanticType::Struct),
(__Field::__field8, __variant) =>
_serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<String>(__variant),
SemanticType::EngineStructure),
}
}
}
#[doc(hidden)]
const VARIANTS: &'static [&'static str] =
&["Void", "Int", "Float", "String", "Object", "Action",
"Vector", "Struct", "EngineStructure"];
_serde::Deserializer::deserialize_enum(__deserializer,
"SemanticType", VARIANTS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticType>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
57pub enum SemanticType {
58 Void,
60 Int,
62 Float,
64 String,
66 Object,
68 Action,
70 Vector,
72 Struct(String),
74 EngineStructure(String),
76}
77
78#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticParameter {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"SemanticParameter", "name", &self.name, "ty", &self.ty,
"is_optional", &self.is_optional, "default", &&self.default)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticParameter {
#[inline]
fn clone(&self) -> SemanticParameter {
SemanticParameter {
name: ::core::clone::Clone::clone(&self.name),
ty: ::core::clone::Clone::clone(&self.ty),
is_optional: ::core::clone::Clone::clone(&self.is_optional),
default: ::core::clone::Clone::clone(&self.default),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticParameter {
#[inline]
fn eq(&self, other: &SemanticParameter) -> bool {
self.is_optional == other.is_optional && self.name == other.name &&
self.ty == other.ty && self.default == other.default
}
}PartialEq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticParameter {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticParameter", false as usize + 1 + 1 + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"name", &self.name)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"ty", &self.ty)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"is_optional", &self.is_optional)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"default", &self.default)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticParameter {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
__ignore,
}
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
3u64 => _serde::__private228::Ok(__Field::__field3),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"name" => _serde::__private228::Ok(__Field::__field0),
"ty" => _serde::__private228::Ok(__Field::__field1),
"is_optional" =>
_serde::__private228::Ok(__Field::__field2),
"default" => _serde::__private228::Ok(__Field::__field3),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"name" => _serde::__private228::Ok(__Field::__field0),
b"ty" => _serde::__private228::Ok(__Field::__field1),
b"is_optional" =>
_serde::__private228::Ok(__Field::__field2),
b"default" => _serde::__private228::Ok(__Field::__field3),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticParameter>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticParameter;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticParameter")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticParameter with 4 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<SemanticType>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticParameter with 4 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct SemanticParameter with 4 elements")),
};
let __field3 =
match _serde::de::SeqAccess::next_element::<Option<Literal>>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(3usize,
&"struct SemanticParameter with 4 elements")),
};
_serde::__private228::Ok(SemanticParameter {
name: __field0,
ty: __field1,
is_optional: __field2,
default: __field3,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<SemanticType> =
_serde::__private228::None;
let mut __field2: _serde::__private228::Option<bool> =
_serde::__private228::None;
let mut __field3:
_serde::__private228::Option<Option<Literal>> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("name"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("ty"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<SemanticType>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("is_optional"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
__Field::__field3 => {
if _serde::__private228::Option::is_some(&__field3) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("default"));
}
__field3 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<Option<Literal>>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("name")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("ty")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("is_optional")?,
};
let __field3 =
match __field3 {
_serde::__private228::Some(__field3) => __field3,
_serde::__private228::None =>
_serde::__private228::de::missing_field("default")?,
};
_serde::__private228::Ok(SemanticParameter {
name: __field0,
ty: __field1,
is_optional: __field2,
default: __field3,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["name", "ty", "is_optional", "default"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticParameter", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticParameter>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
80pub struct SemanticParameter {
81 pub name: String,
83 pub ty: SemanticType,
85 pub is_optional: bool,
87 pub default: Option<Literal>,
89}
90
91#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticFunction {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"SemanticFunction", "name", &self.name, "return_type",
&self.return_type, "parameters", &self.parameters, "has_body",
&self.has_body, "is_builtin", &&self.is_builtin)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticFunction {
#[inline]
fn clone(&self) -> SemanticFunction {
SemanticFunction {
name: ::core::clone::Clone::clone(&self.name),
return_type: ::core::clone::Clone::clone(&self.return_type),
parameters: ::core::clone::Clone::clone(&self.parameters),
has_body: ::core::clone::Clone::clone(&self.has_body),
is_builtin: ::core::clone::Clone::clone(&self.is_builtin),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticFunction {
#[inline]
fn eq(&self, other: &SemanticFunction) -> bool {
self.has_body == other.has_body && self.is_builtin == other.is_builtin
&& self.name == other.name &&
self.return_type == other.return_type &&
self.parameters == other.parameters
}
}PartialEq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticFunction {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticFunction", false as usize + 1 + 1 + 1 + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"name", &self.name)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"return_type", &self.return_type)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"parameters", &self.parameters)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"has_body", &self.has_body)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"is_builtin", &self.is_builtin)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticFunction {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
__field4,
__ignore,
}
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
3u64 => _serde::__private228::Ok(__Field::__field3),
4u64 => _serde::__private228::Ok(__Field::__field4),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"name" => _serde::__private228::Ok(__Field::__field0),
"return_type" =>
_serde::__private228::Ok(__Field::__field1),
"parameters" => _serde::__private228::Ok(__Field::__field2),
"has_body" => _serde::__private228::Ok(__Field::__field3),
"is_builtin" => _serde::__private228::Ok(__Field::__field4),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"name" => _serde::__private228::Ok(__Field::__field0),
b"return_type" =>
_serde::__private228::Ok(__Field::__field1),
b"parameters" =>
_serde::__private228::Ok(__Field::__field2),
b"has_body" => _serde::__private228::Ok(__Field::__field3),
b"is_builtin" =>
_serde::__private228::Ok(__Field::__field4),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticFunction>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticFunction;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticFunction")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticFunction with 5 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<SemanticType>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticFunction with 5 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<Vec<SemanticParameter>>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct SemanticFunction with 5 elements")),
};
let __field3 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(3usize,
&"struct SemanticFunction with 5 elements")),
};
let __field4 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(4usize,
&"struct SemanticFunction with 5 elements")),
};
_serde::__private228::Ok(SemanticFunction {
name: __field0,
return_type: __field1,
parameters: __field2,
has_body: __field3,
is_builtin: __field4,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<SemanticType> =
_serde::__private228::None;
let mut __field2:
_serde::__private228::Option<Vec<SemanticParameter>> =
_serde::__private228::None;
let mut __field3: _serde::__private228::Option<bool> =
_serde::__private228::None;
let mut __field4: _serde::__private228::Option<bool> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("name"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("return_type"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<SemanticType>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("parameters"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<SemanticParameter>>(&mut __map)?);
}
__Field::__field3 => {
if _serde::__private228::Option::is_some(&__field3) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("has_body"));
}
__field3 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
__Field::__field4 => {
if _serde::__private228::Option::is_some(&__field4) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("is_builtin"));
}
__field4 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("name")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("return_type")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("parameters")?,
};
let __field3 =
match __field3 {
_serde::__private228::Some(__field3) => __field3,
_serde::__private228::None =>
_serde::__private228::de::missing_field("has_body")?,
};
let __field4 =
match __field4 {
_serde::__private228::Some(__field4) => __field4,
_serde::__private228::None =>
_serde::__private228::de::missing_field("is_builtin")?,
};
_serde::__private228::Ok(SemanticFunction {
name: __field0,
return_type: __field1,
parameters: __field2,
has_body: __field3,
is_builtin: __field4,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["name", "return_type", "parameters", "has_body",
"is_builtin"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticFunction", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticFunction>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
93pub struct SemanticFunction {
94 pub name: String,
96 pub return_type: SemanticType,
98 pub parameters: Vec<SemanticParameter>,
100 pub has_body: bool,
102 pub is_builtin: bool,
104}
105
106#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticGlobal {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"SemanticGlobal", "name", &self.name, "ty", &self.ty, "is_const",
&&self.is_const)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticGlobal {
#[inline]
fn clone(&self) -> SemanticGlobal {
SemanticGlobal {
name: ::core::clone::Clone::clone(&self.name),
ty: ::core::clone::Clone::clone(&self.ty),
is_const: ::core::clone::Clone::clone(&self.is_const),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticGlobal {
#[inline]
fn eq(&self, other: &SemanticGlobal) -> bool {
self.is_const == other.is_const && self.name == other.name &&
self.ty == other.ty
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SemanticGlobal {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<SemanticType>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticGlobal {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticGlobal", false as usize + 1 + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"name", &self.name)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"ty", &self.ty)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"is_const", &self.is_const)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticGlobal {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __field2, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"name" => _serde::__private228::Ok(__Field::__field0),
"ty" => _serde::__private228::Ok(__Field::__field1),
"is_const" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"name" => _serde::__private228::Ok(__Field::__field0),
b"ty" => _serde::__private228::Ok(__Field::__field1),
b"is_const" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticGlobal>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticGlobal;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticGlobal")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticGlobal with 3 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<SemanticType>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticGlobal with 3 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct SemanticGlobal with 3 elements")),
};
_serde::__private228::Ok(SemanticGlobal {
name: __field0,
ty: __field1,
is_const: __field2,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<SemanticType> =
_serde::__private228::None;
let mut __field2: _serde::__private228::Option<bool> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("name"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("ty"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<SemanticType>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("is_const"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("name")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("ty")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("is_const")?,
};
_serde::__private228::Ok(SemanticGlobal {
name: __field0,
ty: __field1,
is_const: __field2,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["name", "ty", "is_const"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticGlobal", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticGlobal>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
108pub struct SemanticGlobal {
109 pub name: String,
111 pub ty: SemanticType,
113 pub is_const: bool,
115}
116
117#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticField {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "SemanticField",
"name", &self.name, "ty", &&self.ty)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticField {
#[inline]
fn clone(&self) -> SemanticField {
SemanticField {
name: ::core::clone::Clone::clone(&self.name),
ty: ::core::clone::Clone::clone(&self.ty),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticField {
#[inline]
fn eq(&self, other: &SemanticField) -> bool {
self.name == other.name && self.ty == other.ty
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SemanticField {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<SemanticType>;
}
}Eq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticField {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticField", false as usize + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"name", &self.name)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"ty", &self.ty)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticField {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"name" => _serde::__private228::Ok(__Field::__field0),
"ty" => _serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"name" => _serde::__private228::Ok(__Field::__field0),
b"ty" => _serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticField>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticField;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticField")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticField with 2 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<SemanticType>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticField with 2 elements")),
};
_serde::__private228::Ok(SemanticField {
name: __field0,
ty: __field1,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<SemanticType> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("name"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("ty"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<SemanticType>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("name")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("ty")?,
};
_serde::__private228::Ok(SemanticField {
name: __field0,
ty: __field1,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &["name", "ty"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticField", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticField>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
119pub struct SemanticField {
120 pub name: String,
122 pub ty: SemanticType,
124}
125
126#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticStruct {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SemanticStruct", "name", &self.name, "fields", &&self.fields)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticStruct {
#[inline]
fn clone(&self) -> SemanticStruct {
SemanticStruct {
name: ::core::clone::Clone::clone(&self.name),
fields: ::core::clone::Clone::clone(&self.fields),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticStruct {
#[inline]
fn eq(&self, other: &SemanticStruct) -> bool {
self.name == other.name && self.fields == other.fields
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SemanticStruct {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Vec<SemanticField>>;
}
}Eq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticStruct {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticStruct", false as usize + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"name", &self.name)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"fields", &self.fields)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticStruct {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"name" => _serde::__private228::Ok(__Field::__field0),
"fields" => _serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"name" => _serde::__private228::Ok(__Field::__field0),
b"fields" => _serde::__private228::Ok(__Field::__field1),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticStruct>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticStruct;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticStruct")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<String>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticStruct with 2 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<Vec<SemanticField>>(&mut __seq)?
{
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticStruct with 2 elements")),
};
_serde::__private228::Ok(SemanticStruct {
name: __field0,
fields: __field1,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private228::Option<String> =
_serde::__private228::None;
let mut __field1:
_serde::__private228::Option<Vec<SemanticField>> =
_serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("name"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<String>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("fields"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<SemanticField>>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("name")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("fields")?,
};
_serde::__private228::Ok(SemanticStruct {
name: __field0,
fields: __field1,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &["name", "fields"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticStruct", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticStruct>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
128pub struct SemanticStruct {
129 pub name: String,
131 pub fields: Vec<SemanticField>,
133}
134
135#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SemanticModel {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "SemanticModel",
"structs", &self.structs, "globals", &self.globals, "functions",
&&self.functions)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SemanticModel {
#[inline]
fn clone(&self) -> SemanticModel {
SemanticModel {
structs: ::core::clone::Clone::clone(&self.structs),
globals: ::core::clone::Clone::clone(&self.globals),
functions: ::core::clone::Clone::clone(&self.functions),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SemanticModel {
#[inline]
fn eq(&self, other: &SemanticModel) -> bool {
self.structs == other.structs && self.globals == other.globals &&
self.functions == other.functions
}
}PartialEq, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl _serde::Serialize for SemanticModel {
fn serialize<__S>(&self, __serializer: __S)
-> _serde::__private228::Result<__S::Ok, __S::Error> where
__S: _serde::Serializer {
let mut __serde_state =
_serde::Serializer::serialize_struct(__serializer,
"SemanticModel", false as usize + 1 + 1 + 1)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"structs", &self.structs)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"globals", &self.globals)?;
_serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
"functions", &self.functions)?;
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for SemanticModel {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __field2, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private228::Ok(__Field::__field0),
1u64 => _serde::__private228::Ok(__Field::__field1),
2u64 => _serde::__private228::Ok(__Field::__field2),
_ => _serde::__private228::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"structs" => _serde::__private228::Ok(__Field::__field0),
"globals" => _serde::__private228::Ok(__Field::__field1),
"functions" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private228::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"structs" => _serde::__private228::Ok(__Field::__field0),
b"globals" => _serde::__private228::Ok(__Field::__field1),
b"functions" => _serde::__private228::Ok(__Field::__field2),
_ => { _serde::__private228::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private228::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private228::PhantomData<SemanticModel>,
lifetime: _serde::__private228::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = SemanticModel;
fn expecting(&self,
__formatter: &mut _serde::__private228::Formatter)
-> _serde::__private228::fmt::Result {
_serde::__private228::Formatter::write_str(__formatter,
"struct SemanticModel")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<BTreeMap<String,
SemanticStruct>>(&mut __seq)? {
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
&"struct SemanticModel with 3 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<BTreeMap<String,
SemanticGlobal>>(&mut __seq)? {
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
&"struct SemanticModel with 3 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<BTreeMap<String,
SemanticFunction>>(&mut __seq)? {
_serde::__private228::Some(__value) => __value,
_serde::__private228::None =>
return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
&"struct SemanticModel with 3 elements")),
};
_serde::__private228::Ok(SemanticModel {
structs: __field0,
globals: __field1,
functions: __field2,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private228::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0:
_serde::__private228::Option<BTreeMap<String,
SemanticStruct>> = _serde::__private228::None;
let mut __field1:
_serde::__private228::Option<BTreeMap<String,
SemanticGlobal>> = _serde::__private228::None;
let mut __field2:
_serde::__private228::Option<BTreeMap<String,
SemanticFunction>> = _serde::__private228::None;
while let _serde::__private228::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private228::Option::is_some(&__field0) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("structs"));
}
__field0 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<BTreeMap<String,
SemanticStruct>>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private228::Option::is_some(&__field1) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("globals"));
}
__field1 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<BTreeMap<String,
SemanticGlobal>>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private228::Option::is_some(&__field2) {
return _serde::__private228::Err(<__A::Error as
_serde::de::Error>::duplicate_field("functions"));
}
__field2 =
_serde::__private228::Some(_serde::de::MapAccess::next_value::<BTreeMap<String,
SemanticFunction>>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private228::Some(__field0) => __field0,
_serde::__private228::None =>
_serde::__private228::de::missing_field("structs")?,
};
let __field1 =
match __field1 {
_serde::__private228::Some(__field1) => __field1,
_serde::__private228::None =>
_serde::__private228::de::missing_field("globals")?,
};
let __field2 =
match __field2 {
_serde::__private228::Some(__field2) => __field2,
_serde::__private228::None =>
_serde::__private228::de::missing_field("functions")?,
};
_serde::__private228::Ok(SemanticModel {
structs: __field0,
globals: __field1,
functions: __field2,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["structs", "globals", "functions"];
_serde::Deserializer::deserialize_struct(__deserializer,
"SemanticModel", FIELDS,
__Visitor {
marker: _serde::__private228::PhantomData::<SemanticModel>,
lifetime: _serde::__private228::PhantomData,
})
}
}
};Deserialize)]
137pub struct SemanticModel {
138 pub structs: BTreeMap<String, SemanticStruct>,
140 pub globals: BTreeMap<String, SemanticGlobal>,
142 pub functions: BTreeMap<String, SemanticFunction>,
144}
145
146pub fn analyze_script(
152 script: &Script,
153 langspec: Option<&LangSpec>,
154) -> Result<SemanticModel, SemanticError> {
155 analyze_script_with_options(script, langspec, SemanticOptions::default())
156}
157
158pub fn analyze_script_with_options(
164 script: &Script,
165 langspec: Option<&LangSpec>,
166 options: SemanticOptions,
167) -> Result<SemanticModel, SemanticError> {
168 Analyzer::new(script, langspec, options).analyze()
169}
170
171#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ConstantValue {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ConstantValue::Int(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Int",
&__self_0),
ConstantValue::Float(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Float",
&__self_0),
ConstantValue::String(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "String",
&__self_0),
ConstantValue::ObjectId(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ObjectId", &__self_0),
ConstantValue::ObjectSelf =>
::core::fmt::Formatter::write_str(f, "ObjectSelf"),
ConstantValue::ObjectInvalid =>
::core::fmt::Formatter::write_str(f, "ObjectInvalid"),
ConstantValue::LocationInvalid =>
::core::fmt::Formatter::write_str(f, "LocationInvalid"),
ConstantValue::Json(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Json",
&__self_0),
ConstantValue::Vector(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Vector",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ConstantValue {
#[inline]
fn clone(&self) -> ConstantValue {
match self {
ConstantValue::Int(__self_0) =>
ConstantValue::Int(::core::clone::Clone::clone(__self_0)),
ConstantValue::Float(__self_0) =>
ConstantValue::Float(::core::clone::Clone::clone(__self_0)),
ConstantValue::String(__self_0) =>
ConstantValue::String(::core::clone::Clone::clone(__self_0)),
ConstantValue::ObjectId(__self_0) =>
ConstantValue::ObjectId(::core::clone::Clone::clone(__self_0)),
ConstantValue::ObjectSelf => ConstantValue::ObjectSelf,
ConstantValue::ObjectInvalid => ConstantValue::ObjectInvalid,
ConstantValue::LocationInvalid => ConstantValue::LocationInvalid,
ConstantValue::Json(__self_0) =>
ConstantValue::Json(::core::clone::Clone::clone(__self_0)),
ConstantValue::Vector(__self_0) =>
ConstantValue::Vector(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ConstantValue {
#[inline]
fn eq(&self, other: &ConstantValue) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(ConstantValue::Int(__self_0), ConstantValue::Int(__arg1_0))
=> __self_0 == __arg1_0,
(ConstantValue::Float(__self_0),
ConstantValue::Float(__arg1_0)) => __self_0 == __arg1_0,
(ConstantValue::String(__self_0),
ConstantValue::String(__arg1_0)) => __self_0 == __arg1_0,
(ConstantValue::ObjectId(__self_0),
ConstantValue::ObjectId(__arg1_0)) => __self_0 == __arg1_0,
(ConstantValue::Json(__self_0), ConstantValue::Json(__arg1_0))
=> __self_0 == __arg1_0,
(ConstantValue::Vector(__self_0),
ConstantValue::Vector(__arg1_0)) => __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq)]
172enum ConstantValue {
173 Int(i32),
174 Float(f32),
175 String(String),
176 ObjectId(i32),
177 ObjectSelf,
178 ObjectInvalid,
179 LocationInvalid,
180 Json(String),
181 Vector([f32; 3]),
182}
183
184impl ConstantValue {
185 fn ty(&self) -> SemanticType {
186 match self {
187 Self::Int(_) => SemanticType::Int,
188 Self::Float(_) => SemanticType::Float,
189 Self::String(_) => SemanticType::String,
190 Self::ObjectId(_) | Self::ObjectSelf | Self::ObjectInvalid => SemanticType::Object,
191 Self::LocationInvalid => SemanticType::EngineStructure("location".to_string()),
192 Self::Json(_) => SemanticType::EngineStructure("json".to_string()),
193 Self::Vector(_) => SemanticType::Vector,
194 }
195 }
196}
197
198#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ValueBinding {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ValueBinding::Variable { ty: __self_0, is_const: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Variable", "ty", __self_0, "is_const", &__self_1),
ValueBinding::Constant(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Constant", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ValueBinding {
#[inline]
fn clone(&self) -> ValueBinding {
match self {
ValueBinding::Variable { ty: __self_0, is_const: __self_1 } =>
ValueBinding::Variable {
ty: ::core::clone::Clone::clone(__self_0),
is_const: ::core::clone::Clone::clone(__self_1),
},
ValueBinding::Constant(__self_0) =>
ValueBinding::Constant(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ValueBinding {
#[inline]
fn eq(&self, other: &ValueBinding) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(ValueBinding::Variable { ty: __self_0, is_const: __self_1 },
ValueBinding::Variable { ty: __arg1_0, is_const: __arg1_1 })
=> __self_1 == __arg1_1 && __self_0 == __arg1_0,
(ValueBinding::Constant(__self_0),
ValueBinding::Constant(__arg1_0)) => __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq)]
199enum ValueBinding {
200 Variable {
201 ty: SemanticType,
202 is_const: bool,
203 },
204 Constant(ConstantValue),
205}
206
207impl ValueBinding {
208 fn ty(&self) -> SemanticType {
209 match self {
210 Self::Variable {
211 ty, ..
212 } => ty.clone(),
213 Self::Constant(value) => value.ty(),
214 }
215 }
216
217 fn is_const(&self) -> bool {
218 match self {
219 Self::Variable {
220 is_const, ..
221 } => *is_const,
222 Self::Constant(_) => true,
223 }
224 }
225}
226
227#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ScopeBinding {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "ScopeBinding",
"ty", &self.ty, "is_const", &&self.is_const)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ScopeBinding {
#[inline]
fn clone(&self) -> ScopeBinding {
ScopeBinding {
ty: ::core::clone::Clone::clone(&self.ty),
is_const: ::core::clone::Clone::clone(&self.is_const),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ScopeBinding {
#[inline]
fn eq(&self, other: &ScopeBinding) -> bool {
self.is_const == other.is_const && self.ty == other.ty
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ScopeBinding {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<SemanticType>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq)]
228struct ScopeBinding {
229 ty: SemanticType,
230 is_const: bool,
231}
232
233#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FunctionInfo {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "FunctionInfo",
"signature", &self.signature, "declaration_span",
&&self.declaration_span)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for FunctionInfo {
#[inline]
fn clone(&self) -> FunctionInfo {
FunctionInfo {
signature: ::core::clone::Clone::clone(&self.signature),
declaration_span: ::core::clone::Clone::clone(&self.declaration_span),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for FunctionInfo {
#[inline]
fn eq(&self, other: &FunctionInfo) -> bool {
self.signature == other.signature &&
self.declaration_span == other.declaration_span
}
}PartialEq)]
234struct FunctionInfo {
235 signature: SemanticFunction,
236 declaration_span: crate::Span,
237}
238
239#[derive(#[automatically_derived]
impl ::core::fmt::Debug for AnalysisContext {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"AnalysisContext", "switch_stack", &&self.switch_stack)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for AnalysisContext {
#[inline]
fn default() -> AnalysisContext {
AnalysisContext { switch_stack: ::core::default::Default::default() }
}
}Default)]
240struct AnalysisContext {
241 switch_stack: Vec<SwitchContext>,
242}
243
244#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SwitchContext {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "SwitchContext",
"case_values", &self.case_values, "has_default",
&self.has_default, "scope_decl_counts", &&self.scope_decl_counts)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for SwitchContext {
#[inline]
fn default() -> SwitchContext {
SwitchContext {
case_values: ::core::default::Default::default(),
has_default: ::core::default::Default::default(),
scope_decl_counts: ::core::default::Default::default(),
}
}
}Default)]
245struct SwitchContext {
246 case_values: BTreeSet<i32>,
247 has_default: bool,
248 scope_decl_counts: Vec<usize>,
249}
250
251impl AnalysisContext {
252 fn enter_scope(&mut self) {
253 for switch in &mut self.switch_stack {
254 switch.scope_decl_counts.push(0);
255 }
256 }
257
258 fn exit_scope(&mut self) {
259 for switch in &mut self.switch_stack {
260 switch.scope_decl_counts.pop();
261 if switch.scope_decl_counts.is_empty() {
262 switch.scope_decl_counts.push(0);
263 }
264 }
265 }
266
267 fn record_declaration(&mut self) {
268 for switch in &mut self.switch_stack {
269 if let Some(current) = switch.scope_decl_counts.last_mut() {
270 *current += 1;
271 }
272 }
273 }
274
275 fn current_switch_mut(&mut self) -> Option<&mut SwitchContext> {
276 self.switch_stack.last_mut()
277 }
278}
279
280impl SwitchContext {
281 fn has_live_declarations(&self) -> bool {
282 self.scope_decl_counts.iter().any(|count| *count > 0)
283 }
284}
285
286struct Analyzer<'a> {
287 script: &'a Script,
288 options: SemanticOptions,
289 builtin_constants: BTreeMap<String, ConstantValue>,
290 global_constants: BTreeMap<String, ConstantValue>,
291 functions: BTreeMap<String, FunctionInfo>,
292 structs: BTreeMap<String, SemanticStruct>,
293 globals: BTreeMap<String, SemanticGlobal>,
294}
295
296impl<'a> Analyzer<'a> {
297 fn new(script: &'a Script, langspec: Option<&LangSpec>, options: SemanticOptions) -> Self {
298 let mut builtin_constants = BTreeMap::new();
299 let mut functions = BTreeMap::new();
300
301 if let Some(langspec) = langspec {
302 for constant in &langspec.constants {
303 if let Some(value) = constant_from_builtin_value(&constant.value) {
304 builtin_constants.insert(constant.name.clone(), value);
305 }
306 }
307
308 for function in &langspec.functions {
309 let parameters = function
310 .parameters
311 .iter()
312 .map(|parameter| SemanticParameter {
313 name: parameter.name.clone(),
314 ty: semantic_type_from_builtin_type(¶meter.ty),
315 is_optional: parameter.default.is_some(),
316 default: parameter
317 .default
318 .as_ref()
319 .and_then(literal_from_builtin_value),
320 })
321 .collect::<Vec<_>>();
322
323 functions.insert(
324 function.name.clone(),
325 FunctionInfo {
326 signature: SemanticFunction {
327 name: function.name.clone(),
328 return_type: semantic_type_from_builtin_type(&function.return_type),
329 parameters,
330 has_body: false,
331 is_builtin: true,
332 },
333 declaration_span: crate::Span::new(crate::SourceId::new(0), 0, 0),
334 },
335 );
336 }
337 }
338
339 Self {
340 script,
341 options,
342 builtin_constants,
343 global_constants: BTreeMap::new(),
344 functions,
345 structs: BTreeMap::new(),
346 globals: BTreeMap::new(),
347 }
348 }
349
350 fn analyze(mut self) -> Result<SemanticModel, SemanticError> {
351 self.collect_structs()?;
352 self.collect_const_globals_for_function_defaults()?;
353 self.collect_functions()?;
354 self.collect_globals()?;
355 self.analyze_function_bodies()?;
356 self.validate_entrypoint()?;
357
358 Ok(SemanticModel {
359 structs: self.structs,
360 globals: self.globals,
361 functions: self
362 .functions
363 .into_iter()
364 .map(|(name, info)| (name, info.signature))
365 .collect(),
366 })
367 }
368
369 fn collect_const_globals_for_function_defaults(&mut self) -> Result<(), SemanticError> {
370 for item in &self.script.items {
371 let TopLevelItem::Global(declaration) = item else {
372 continue;
373 };
374 if !declaration.ty.is_const {
375 continue;
376 }
377
378 let ty = self.resolve_type(&declaration.ty)?;
379 for declarator in &declaration.declarators {
380 let value = if let Some(initializer) = &declarator.initializer {
381 self.evaluate_constant_expr(initializer).ok_or_else(|| {
382 SemanticError::new(
383 CompilerErrorCode::InvalidValueAssignedToConstant,
384 initializer.span,
385 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant {0:?} must be initialized with a constant value",
declarator.name))
})format!(
386 "constant {:?} must be initialized with a constant value",
387 declarator.name
388 ),
389 )
390 })?
391 } else {
392 default_constant_value(&ty).ok_or_else(|| {
393 SemanticError::new(
394 CompilerErrorCode::InvalidValueAssignedToConstant,
395 declarator.span,
396 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant {0:?} type {1:?} does not support default constant initialization",
declarator.name, ty))
})format!(
397 "constant {:?} type {:?} does not support default constant \
398 initialization",
399 declarator.name, ty
400 ),
401 )
402 })?
403 };
404 if !types_compatible(&ty, &value.ty()) {
405 return Err(SemanticError::new(
406 CompilerErrorCode::InvalidValueAssignedToConstant,
407 declarator
408 .initializer
409 .as_ref()
410 .map_or(declarator.span, |initializer| initializer.span),
411 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant {0:?} initializer does not match type {1:?}",
declarator.name, ty))
})format!(
412 "constant {:?} initializer does not match type {:?}",
413 declarator.name, ty
414 ),
415 ));
416 }
417
418 self.global_constants.insert(declarator.name.clone(), value);
419 }
420 }
421
422 Ok(())
423 }
424
425 fn collect_structs(&mut self) -> Result<(), SemanticError> {
426 for item in &self.script.items {
427 let TopLevelItem::Struct(definition) = item else {
428 continue;
429 };
430
431 if self.structs.contains_key(&definition.name) {
432 return Err(SemanticError::new(
433 CompilerErrorCode::StructureRedefined,
434 definition.span,
435 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("structure {0:?} was defined more than once",
definition.name))
})format!("structure {:?} was defined more than once", definition.name),
436 ));
437 }
438
439 let mut fields = Vec::new();
440 let mut seen_names = BTreeMap::<String, crate::Span>::new();
441 for declaration in &definition.fields {
442 let field_type = self.resolve_type(&declaration.ty)?;
443 for field in &declaration.names {
444 if seen_names.contains_key(&field.name) {
445 return Err(SemanticError::new(
446 CompilerErrorCode::VariableUsedTwiceInSameStructure,
447 field.span,
448 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("field {0:?} was used twice in structure {1:?}",
field.name, definition.name))
})format!(
449 "field {:?} was used twice in structure {:?}",
450 field.name, definition.name
451 ),
452 ));
453 }
454 seen_names.insert(field.name.clone(), field.span);
455 fields.push(SemanticField {
456 name: field.name.clone(),
457 ty: field_type.clone(),
458 });
459 }
460 }
461
462 self.structs.insert(
463 definition.name.clone(),
464 SemanticStruct {
465 name: definition.name.clone(),
466 fields,
467 },
468 );
469 }
470
471 Ok(())
472 }
473
474 fn collect_functions(&mut self) -> Result<(), SemanticError> {
475 for item in &self.script.items {
476 let TopLevelItem::Function(function) = item else {
477 continue;
478 };
479
480 let signature = self.resolve_function_signature(function)?;
481 if let Some(existing) = self.functions.get_mut(&function.name) {
482 if existing.signature.is_builtin {
483 return Err(SemanticError::new(
484 CompilerErrorCode::FunctionImplementationAndDefinitionDiffer,
485 function.span,
486 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function {0:?} conflicts with builtin declaration",
function.name))
})format!(
487 "function {:?} conflicts with builtin declaration",
488 function.name
489 ),
490 ));
491 }
492
493 if existing.signature.return_type != signature.return_type
494 || !parameters_match(&existing.signature.parameters, &signature.parameters)
495 {
496 return Err(SemanticError::new(
497 CompilerErrorCode::FunctionImplementationAndDefinitionDiffer,
498 function.span,
499 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function {0:?} declaration differs from previous declaration",
function.name))
})format!(
500 "function {:?} declaration differs from previous declaration",
501 function.name
502 ),
503 ));
504 }
505
506 for (existing_parameter, new_parameter) in existing
507 .signature
508 .parameters
509 .iter_mut()
510 .zip(&signature.parameters)
511 {
512 if existing_parameter.default.is_none() && new_parameter.default.is_some() {
513 existing_parameter
514 .default
515 .clone_from(&new_parameter.default);
516 existing_parameter.is_optional = true;
517 }
518 }
519
520 if function.body.is_some() {
521 if existing.signature.has_body {
522 return Err(SemanticError::new(
523 CompilerErrorCode::DuplicateFunctionImplementation,
524 function.span,
525 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function {0:?} was implemented more than once",
function.name))
})format!(
526 "function {:?} was implemented more than once",
527 function.name
528 ),
529 ));
530 }
531 existing.signature.has_body = true;
532 }
533 continue;
534 }
535
536 self.functions.insert(
537 function.name.clone(),
538 FunctionInfo {
539 declaration_span: function.span,
540 signature,
541 },
542 );
543 }
544
545 Ok(())
546 }
547
548 fn collect_globals(&mut self) -> Result<(), SemanticError> {
549 for item in &self.script.items {
550 let TopLevelItem::Global(declaration) = item else {
551 continue;
552 };
553
554 let ty = self.resolve_type(&declaration.ty)?;
555 for declarator in &declaration.declarators {
556 if self.globals.contains_key(&declarator.name) {
557 return Err(SemanticError::new(
558 CompilerErrorCode::VariableAlreadyUsedWithinScope,
559 declarator.span,
560 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("global {0:?} was declared more than once",
declarator.name))
})format!("global {:?} was declared more than once", declarator.name),
561 ));
562 }
563
564 if declaration.ty.is_const {
565 let value = if let Some(initializer) = &declarator.initializer {
566 self.evaluate_constant_expr(initializer).ok_or_else(|| {
567 SemanticError::new(
568 CompilerErrorCode::InvalidValueAssignedToConstant,
569 initializer.span,
570 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant {0:?} must be initialized with a constant value",
declarator.name))
})format!(
571 "constant {:?} must be initialized with a constant value",
572 declarator.name
573 ),
574 )
575 })?
576 } else {
577 default_constant_value(&ty).ok_or_else(|| {
578 SemanticError::new(
579 CompilerErrorCode::InvalidValueAssignedToConstant,
580 declarator.span,
581 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant {0:?} type {1:?} does not support default constant initialization",
declarator.name, ty))
})format!(
582 "constant {:?} type {:?} does not support default constant \
583 initialization",
584 declarator.name, ty
585 ),
586 )
587 })?
588 };
589 if !types_compatible(&ty, &value.ty()) {
590 return Err(SemanticError::new(
591 CompilerErrorCode::InvalidValueAssignedToConstant,
592 declarator
593 .initializer
594 .as_ref()
595 .map_or(declarator.span, |initializer| initializer.span),
596 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant {0:?} initializer does not match type {1:?}",
declarator.name, ty))
})format!(
597 "constant {:?} initializer does not match type {:?}",
598 declarator.name, ty
599 ),
600 ));
601 }
602
603 self.global_constants
604 .insert(declarator.name.clone(), value.clone());
605 } else if let Some(initializer) = &declarator.initializer {
606 let initializer_type = self
607 .analyze_expr(initializer, &mut Vec::new())
608 .map(|resolved| resolved.ty)?;
609 if !types_compatible(&ty, &initializer_type) {
610 return Err(SemanticError::new(
611 CompilerErrorCode::MismatchedTypes,
612 initializer.span,
613 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("initializer for global {0:?} has type {1:?}, expected {2:?}",
declarator.name, initializer_type, ty))
})format!(
614 "initializer for global {:?} has type {:?}, expected {:?}",
615 declarator.name, initializer_type, ty
616 ),
617 ));
618 }
619 }
620
621 self.globals.insert(
622 declarator.name.clone(),
623 SemanticGlobal {
624 name: declarator.name.clone(),
625 ty: ty.clone(),
626 is_const: declaration.ty.is_const,
627 },
628 );
629 }
630 }
631
632 Ok(())
633 }
634
635 fn analyze_function_bodies(&self) -> Result<(), SemanticError> {
636 for item in &self.script.items {
637 let TopLevelItem::Function(function) = item else {
638 continue;
639 };
640 let Some(body) = &function.body else {
641 continue;
642 };
643
644 let info = self.functions.get(&function.name).ok_or_else(|| {
645 SemanticError::new(
646 CompilerErrorCode::UnknownStateInCompiler,
647 function.span,
648 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function {0:?} missing from semantic table",
function.name))
})format!("function {:?} missing from semantic table", function.name),
649 )
650 })?;
651 let mut scopes = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[BTreeMap::new(), BTreeMap::new()]))vec![BTreeMap::new(), BTreeMap::new()];
652 for (signature_parameter, source_parameter) in
653 info.signature.parameters.iter().zip(&function.parameters)
654 {
655 let (parameter_scope, _) = scopes.split_at_mut(1);
656 insert_scope_binding(
657 parameter_scope,
658 &source_parameter.name,
659 signature_parameter.ty.clone(),
660 false,
661 source_parameter.span,
662 )?;
663 }
664
665 let mut context = AnalysisContext::default();
666 self.analyze_block(
667 body,
668 &mut scopes,
669 &info.signature.return_type,
670 true,
671 &mut context,
672 )?;
673
674 if info.signature.return_type != SemanticType::Void
675 && !statement_guarantees_return(&Stmt::Block(body.clone()))
676 {
677 return Err(SemanticError::new(
678 CompilerErrorCode::NotAllControlPathsReturnAValue,
679 function.span,
680 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function {0:?} does not return a value on all control paths",
function.name))
})format!(
681 "function {:?} does not return a value on all control paths",
682 function.name
683 ),
684 ));
685 }
686 }
687
688 Ok(())
689 }
690
691 fn analyze_block(
692 &self,
693 block: &BlockStmt,
694 scopes: &mut Vec<BTreeMap<String, ScopeBinding>>,
695 return_type: &SemanticType,
696 is_function_body: bool,
697 context: &mut AnalysisContext,
698 ) -> Result<(), SemanticError> {
699 if !is_function_body {
700 scopes.push(BTreeMap::new());
701 context.enter_scope();
702 }
703
704 for statement in &block.statements {
705 self.analyze_stmt(statement, scopes, return_type, context)?;
706 }
707
708 if !is_function_body {
709 context.exit_scope();
710 scopes.pop();
711 }
712
713 Ok(())
714 }
715
716 #[allow(clippy::too_many_lines)]
717 fn analyze_stmt(
718 &self,
719 statement: &Stmt,
720 scopes: &mut Vec<BTreeMap<String, ScopeBinding>>,
721 return_type: &SemanticType,
722 context: &mut AnalysisContext,
723 ) -> Result<(), SemanticError> {
724 match statement {
725 Stmt::Block(block) => self.analyze_block(block, scopes, return_type, false, context),
726 Stmt::Declaration(declaration) => {
727 if declaration.ty.is_const {
728 return Err(SemanticError::new(
729 CompilerErrorCode::ConstKeywordCannotBeUsedOnNonGlobalVariables,
730 declaration.span,
731 "const cannot be used on non-global variables",
732 ));
733 }
734
735 let ty = self.resolve_type(&declaration.ty)?;
736 for declarator in &declaration.declarators {
737 if current_scope_contains(scopes, &declarator.name) {
738 return Err(SemanticError::new(
739 CompilerErrorCode::VariableAlreadyUsedWithinScope,
740 declarator.span,
741 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("variable {0:?} was already declared in this scope",
declarator.name))
})format!(
742 "variable {:?} was already declared in this scope",
743 declarator.name
744 ),
745 ));
746 }
747
748 if let Some(initializer) = &declarator.initializer {
749 let initializer_type = self.analyze_expr(initializer, scopes)?.ty;
750 if !types_compatible(&ty, &initializer_type) {
751 return Err(SemanticError::new(
752 CompilerErrorCode::MismatchedTypes,
753 initializer.span,
754 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("initializer for {0:?} has type {1:?}, expected {2:?}",
declarator.name, initializer_type, ty))
})format!(
755 "initializer for {:?} has type {:?}, expected {:?}",
756 declarator.name, initializer_type, ty
757 ),
758 ));
759 }
760 }
761
762 let Some(scope) = scopes.last_mut() else {
763 return Err(SemanticError::new(
764 CompilerErrorCode::UnknownStateInCompiler,
765 declarator.span,
766 "scope stack must be non-empty",
767 ));
768 };
769 scope.insert(
770 declarator.name.clone(),
771 ScopeBinding {
772 ty: ty.clone(),
773 is_const: false,
774 },
775 );
776 }
777 context.record_declaration();
778 Ok(())
779 }
780 Stmt::Expression(statement) => {
781 self.analyze_expr(&statement.expr, scopes)?;
782 Ok(())
783 }
784 Stmt::If(statement) => {
785 let condition = self.analyze_expr(&statement.condition, scopes)?;
786 if condition.ty != SemanticType::Int {
787 return Err(SemanticError::new(
788 CompilerErrorCode::NonIntegerExpressionWhereIntegerRequired,
789 statement.condition.span,
790 "if condition must evaluate to int",
791 ));
792 }
793 self.analyze_stmt(&statement.then_branch, scopes, return_type, context)?;
794 if let Some(branch) = &statement.else_branch {
795 self.analyze_stmt(branch, scopes, return_type, context)?;
796 }
797 Ok(())
798 }
799 Stmt::Switch(statement) => {
800 let condition = self.analyze_expr(&statement.condition, scopes)?;
801 if condition.ty != SemanticType::Int {
802 return Err(SemanticError::new(
803 CompilerErrorCode::SwitchMustEvaluateToAnInteger,
804 statement.condition.span,
805 "switch condition must evaluate to int",
806 ));
807 }
808 context.switch_stack.push(SwitchContext {
809 case_values: BTreeSet::new(),
810 has_default: false,
811 scope_decl_counts: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[0]))vec![0],
812 });
813 let result = self.analyze_stmt(&statement.body, scopes, return_type, context);
814 context.switch_stack.pop();
815 result
816 }
817 Stmt::Return(statement) => match (&statement.value, return_type) {
818 (None, SemanticType::Void) => Ok(()),
819 (Some(value), SemanticType::Void) => Err(SemanticError::new(
820 CompilerErrorCode::ReturnTypeAndFunctionTypeMismatched,
821 value.span,
822 "void functions cannot return a value",
823 )),
824 (None, _) => Err(SemanticError::new(
825 CompilerErrorCode::ReturnTypeAndFunctionTypeMismatched,
826 statement.span,
827 "non-void functions must return a value",
828 )),
829 (Some(value), expected) => {
830 let actual = self.analyze_expr(value, scopes)?.ty;
831 if !types_compatible(expected, &actual) {
832 return Err(SemanticError::new(
833 CompilerErrorCode::ReturnTypeAndFunctionTypeMismatched,
834 value.span,
835 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("return expression has type {0:?}, expected {1:?}",
actual, expected))
})format!("return expression has type {actual:?}, expected {expected:?}"),
836 ));
837 }
838 Ok(())
839 }
840 },
841 Stmt::While(statement) => {
842 let condition = self.analyze_expr(&statement.condition, scopes)?;
843 if condition.ty != SemanticType::Int {
844 return Err(SemanticError::new(
845 CompilerErrorCode::NonIntegerExpressionWhereIntegerRequired,
846 statement.condition.span,
847 "while condition must evaluate to int",
848 ));
849 }
850 self.analyze_stmt(&statement.body, scopes, return_type, context)
851 }
852 Stmt::DoWhile(statement) => {
853 self.analyze_stmt(&statement.body, scopes, return_type, context)?;
854 let condition = self.analyze_expr(&statement.condition, scopes)?;
855 if condition.ty != SemanticType::Int {
856 return Err(SemanticError::new(
857 CompilerErrorCode::NonIntegerExpressionWhereIntegerRequired,
858 statement.condition.span,
859 "do-while condition must evaluate to int",
860 ));
861 }
862 Ok(())
863 }
864 Stmt::For(statement) => {
865 if let Some(initializer) = &statement.initializer {
866 self.analyze_expr(initializer, scopes)?;
867 }
868 if let Some(condition) = &statement.condition {
869 let resolved = self.analyze_expr(condition, scopes)?;
870 if resolved.ty != SemanticType::Int {
871 return Err(SemanticError::new(
872 CompilerErrorCode::NonIntegerExpressionWhereIntegerRequired,
873 condition.span,
874 "for condition must evaluate to int",
875 ));
876 }
877 }
878 if let Some(update) = &statement.update {
879 self.analyze_expr(update, scopes)?;
880 }
881 self.analyze_stmt(&statement.body, scopes, return_type, context)
882 }
883 Stmt::Case(statement) => {
884 let value = self
885 .evaluate_switch_case_value(&statement.value)
886 .ok_or_else(|| {
887 SemanticError::new(
888 CompilerErrorCode::CaseParameterNotAConstantInteger,
889 statement.value.span,
890 "case expression must be a constant integer or string",
891 )
892 })?;
893 let Some(current_switch) = context.current_switch_mut() else {
894 return Err(SemanticError::new(
895 CompilerErrorCode::UnknownStateInCompiler,
896 statement.span,
897 "case labels must appear within a switch statement",
898 ));
899 };
900 if current_switch.has_live_declarations() {
901 return Err(SemanticError::new(
902 CompilerErrorCode::JumpingOverDeclarationStatementsCaseDisallowed,
903 statement.span,
904 "case label would jump over active declarations",
905 ));
906 }
907 if !current_switch.case_values.insert(value) {
908 return Err(SemanticError::new(
909 CompilerErrorCode::MultipleCaseConstantStatementsWithinSwitch,
910 statement.span,
911 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("case value {0:?} was used more than once in this switch",
value))
})format!("case value {value:?} was used more than once in this switch"),
912 ));
913 }
914 Ok(())
915 }
916 Stmt::Default(statement) => {
917 let Some(current_switch) = context.current_switch_mut() else {
918 return Err(SemanticError::new(
919 CompilerErrorCode::UnknownStateInCompiler,
920 statement.span,
921 "default labels must appear within a switch statement",
922 ));
923 };
924 if current_switch.has_live_declarations() {
925 return Err(SemanticError::new(
926 CompilerErrorCode::JumpingOverDeclarationStatementsDefaultDisallowed,
927 statement.span,
928 "default label would jump over active declarations",
929 ));
930 }
931 if current_switch.has_default {
932 return Err(SemanticError::new(
933 CompilerErrorCode::MultipleDefaultStatementsWithinSwitch,
934 statement.span,
935 "default label appeared more than once in this switch",
936 ));
937 }
938 current_switch.has_default = true;
939 Ok(())
940 }
941 Stmt::Break(_) | Stmt::Continue(_) | Stmt::Empty(_) => Ok(()),
942 }
943 }
944
945 #[allow(clippy::too_many_lines)]
946 fn analyze_expr(
947 &self,
948 expr: &Expr,
949 scopes: &mut Vec<BTreeMap<String, ScopeBinding>>,
950 ) -> Result<ResolvedExpr, SemanticError> {
951 match &expr.kind {
952 ExprKind::Literal(literal) => Ok(ResolvedExpr {
953 ty: semantic_type_from_literal(literal),
954 is_lvalue: false,
955 is_const: !#[allow(non_exhaustive_omitted_patterns)] match literal {
Literal::Magic(_) => true,
_ => false,
}matches!(literal, Literal::Magic(_)),
956 }),
957 ExprKind::Identifier(name) => {
958 let binding = self.lookup_value(name, scopes).ok_or_else(|| {
959 SemanticError::new(
960 CompilerErrorCode::UndefinedIdentifier,
961 expr.span,
962 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("undefined identifier {0:?}", name))
})format!("undefined identifier {name:?}"),
963 )
964 })?;
965 Ok(ResolvedExpr {
966 ty: binding.ty(),
967 is_lvalue: #[allow(non_exhaustive_omitted_patterns)] match binding {
ValueBinding::Variable { .. } => true,
_ => false,
}matches!(binding, ValueBinding::Variable { .. }),
968 is_const: binding.is_const(),
969 })
970 }
971 ExprKind::Call {
972 callee,
973 arguments,
974 } => {
975 let ExprKind::Identifier(name) = &callee.kind else {
976 return Err(SemanticError::new(
977 CompilerErrorCode::UndefinedIdentifier,
978 callee.span,
979 "only direct identifier calls are supported",
980 ));
981 };
982
983 let function = self.functions.get(name).ok_or_else(|| {
984 SemanticError::new(
985 CompilerErrorCode::UndefinedIdentifier,
986 callee.span,
987 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("undefined function {0:?}", name))
})format!("undefined function {name:?}"),
988 )
989 })?;
990
991 if arguments.len() > function.signature.parameters.len() {
992 return Err(SemanticError::new(
993 CompilerErrorCode::DeclarationDoesNotMatchParameters,
994 expr.span,
995 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("call to {0:?} passed too many parameters: {1} > {2}",
name, arguments.len(), function.signature.parameters.len()))
})format!(
996 "call to {:?} passed too many parameters: {} > {}",
997 name,
998 arguments.len(),
999 function.signature.parameters.len()
1000 ),
1001 ));
1002 }
1003
1004 let non_optional = function
1005 .signature
1006 .parameters
1007 .iter()
1008 .filter(|parameter| !parameter.is_optional)
1009 .count();
1010 if arguments.len() < non_optional {
1011 return Err(SemanticError::new(
1012 CompilerErrorCode::DeclarationDoesNotMatchParameters,
1013 expr.span,
1014 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("call to {0:?} did not supply enough parameters: {1} < {2}",
name, arguments.len(), non_optional))
})format!(
1015 "call to {:?} did not supply enough parameters: {} < {}",
1016 name,
1017 arguments.len(),
1018 non_optional
1019 ),
1020 ));
1021 }
1022
1023 for (argument, parameter) in arguments.iter().zip(&function.signature.parameters) {
1024 let resolved = self.analyze_expr(argument, scopes)?;
1025 let is_action_argument = #[allow(non_exhaustive_omitted_patterns)] match (¶meter.ty,
&argument.kind) {
(SemanticType::Action, ExprKind::Call { callee: _, arguments: _ }) =>
true,
_ => false,
}matches!(
1026 (¶meter.ty, &argument.kind),
1027 (
1028 SemanticType::Action,
1029 ExprKind::Call {
1030 callee: _,
1031 arguments: _,
1032 }
1033 )
1034 ) && resolved.ty == SemanticType::Void;
1035 if !is_action_argument && !types_compatible(¶meter.ty, &resolved.ty) {
1036 return Err(SemanticError::new(
1037 CompilerErrorCode::DeclarationDoesNotMatchParameters,
1038 argument.span,
1039 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("parameter {0:?} expects {1:?}, got {2:?}",
parameter.name, parameter.ty, resolved.ty))
})format!(
1040 "parameter {:?} expects {:?}, got {:?}",
1041 parameter.name, parameter.ty, resolved.ty
1042 ),
1043 ));
1044 }
1045 }
1046
1047 Ok(ResolvedExpr {
1048 ty: function.signature.return_type.clone(),
1049 is_lvalue: false,
1050 is_const: false,
1051 })
1052 }
1053 ExprKind::FieldAccess {
1054 base,
1055 field,
1056 } => {
1057 let resolved_base = self.analyze_expr(base, scopes)?;
1058 let field_type = match &resolved_base.ty {
1059 SemanticType::Vector => match field.as_str() {
1060 "x" | "y" | "z" => Ok(SemanticType::Float),
1061 _ => Err(SemanticError::new(
1062 CompilerErrorCode::UndefinedFieldInStructure,
1063 expr.span,
1064 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("field {0:?} does not exist on vector",
field))
})format!("field {field:?} does not exist on vector"),
1065 )),
1066 },
1067 SemanticType::Struct(name) => self
1068 .structs
1069 .get(name)
1070 .and_then(|structure| {
1071 structure
1072 .fields
1073 .iter()
1074 .find(|candidate| candidate.name == *field)
1075 .map(|candidate| candidate.ty.clone())
1076 })
1077 .ok_or_else(|| {
1078 SemanticError::new(
1079 CompilerErrorCode::UndefinedFieldInStructure,
1080 expr.span,
1081 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("field {0:?} does not exist on structure {1:?}",
field, name))
})format!("field {field:?} does not exist on structure {name:?}"),
1082 )
1083 }),
1084 _ => Err(SemanticError::new(
1085 CompilerErrorCode::LeftOfStructurePartNotStructure,
1086 base.span,
1087 "left side of field access must be a structure",
1088 )),
1089 }?;
1090
1091 Ok(ResolvedExpr {
1092 ty: field_type,
1093 is_lvalue: resolved_base.is_lvalue,
1094 is_const: resolved_base.is_const,
1095 })
1096 }
1097 ExprKind::Unary {
1098 op,
1099 expr: inner,
1100 } => {
1101 let resolved = self.analyze_expr(inner, scopes)?;
1102 match op {
1103 UnaryOp::Negate => match resolved.ty {
1104 SemanticType::Int | SemanticType::Float => Ok(ResolvedExpr {
1105 ty: resolved.ty,
1106 is_lvalue: false,
1107 is_const: resolved.is_const,
1108 }),
1109 _ => Err(SemanticError::new(
1110 CompilerErrorCode::ArithmeticOperationHasInvalidOperands,
1111 expr.span,
1112 "negation requires an int or float operand",
1113 )),
1114 },
1115 UnaryOp::OnesComplement => {
1116 if resolved.ty != SemanticType::Int {
1117 return Err(SemanticError::new(
1118 CompilerErrorCode::ArithmeticOperationHasInvalidOperands,
1119 expr.span,
1120 "ones-complement requires an int operand",
1121 ));
1122 }
1123 Ok(ResolvedExpr {
1124 ty: SemanticType::Int,
1125 is_lvalue: false,
1126 is_const: resolved.is_const,
1127 })
1128 }
1129 UnaryOp::BooleanNot => {
1130 if resolved.ty != SemanticType::Int {
1131 return Err(SemanticError::new(
1132 CompilerErrorCode::LogicalOperationHasInvalidOperands,
1133 expr.span,
1134 "boolean-not requires an int operand",
1135 ));
1136 }
1137 Ok(ResolvedExpr {
1138 ty: SemanticType::Int,
1139 is_lvalue: false,
1140 is_const: resolved.is_const,
1141 })
1142 }
1143 UnaryOp::PreIncrement
1144 | UnaryOp::PreDecrement
1145 | UnaryOp::PostIncrement
1146 | UnaryOp::PostDecrement => {
1147 if resolved.ty != SemanticType::Int || !resolved.is_lvalue {
1148 return Err(SemanticError::new(
1149 CompilerErrorCode::OperandMustBeAnIntegerLValue,
1150 expr.span,
1151 "increment and decrement require an int lvalue",
1152 ));
1153 }
1154 Ok(ResolvedExpr {
1155 ty: SemanticType::Int,
1156 is_lvalue: false,
1157 is_const: false,
1158 })
1159 }
1160 }
1161 }
1162 ExprKind::Binary {
1163 op,
1164 left,
1165 right,
1166 } => {
1167 let left = self.analyze_expr(left, scopes)?;
1168 let right = self.analyze_expr(right, scopes)?;
1169 let ty = Self::binary_result_type(*op, &left.ty, &right.ty, expr.span)?;
1170 Ok(ResolvedExpr {
1171 ty,
1172 is_lvalue: false,
1173 is_const: left.is_const && right.is_const,
1174 })
1175 }
1176 ExprKind::Conditional {
1177 condition: _,
1178 when_true,
1179 when_false,
1180 } => {
1181 let when_true = self.analyze_expr(when_true, scopes)?;
1182 let when_false = self.analyze_expr(when_false, scopes)?;
1183 if !types_compatible(&when_true.ty, &when_false.ty) {
1184 return Err(SemanticError::new(
1185 CompilerErrorCode::ConditionalMustHaveMatchingReturnTypes,
1186 expr.span,
1187 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("conditional expression branches must match: {0:?} vs {1:?}",
when_true.ty, when_false.ty))
})format!(
1188 "conditional expression branches must match: {:?} vs {:?}",
1189 when_true.ty, when_false.ty
1190 ),
1191 ));
1192 }
1193 Ok(ResolvedExpr {
1194 ty: when_true.ty,
1195 is_lvalue: false,
1196 is_const: when_true.is_const && when_false.is_const,
1197 })
1198 }
1199 ExprKind::Assignment {
1200 op,
1201 left,
1202 right,
1203 } => {
1204 let left_resolved = self.analyze_expr(left, scopes)?;
1205 if !left_resolved.is_lvalue {
1206 return Err(SemanticError::new(
1207 CompilerErrorCode::BadLValue,
1208 left.span,
1209 "left side of assignment must be an lvalue",
1210 ));
1211 }
1212 let right_resolved = self.analyze_expr(right, scopes)?;
1213 let result_type = match op {
1214 AssignmentOp::Assign => right_resolved.ty.clone(),
1215 AssignmentOp::AssignMinus => Self::binary_result_type(
1216 BinaryOp::Subtract,
1217 &left_resolved.ty,
1218 &right_resolved.ty,
1219 expr.span,
1220 )?,
1221 AssignmentOp::AssignPlus => Self::binary_result_type(
1222 BinaryOp::Add,
1223 &left_resolved.ty,
1224 &right_resolved.ty,
1225 expr.span,
1226 )?,
1227 AssignmentOp::AssignMultiply => Self::binary_result_type(
1228 BinaryOp::Multiply,
1229 &left_resolved.ty,
1230 &right_resolved.ty,
1231 expr.span,
1232 )?,
1233 AssignmentOp::AssignDivide => Self::binary_result_type(
1234 BinaryOp::Divide,
1235 &left_resolved.ty,
1236 &right_resolved.ty,
1237 expr.span,
1238 )?,
1239 AssignmentOp::AssignModulus => Self::binary_result_type(
1240 BinaryOp::Modulus,
1241 &left_resolved.ty,
1242 &right_resolved.ty,
1243 expr.span,
1244 )?,
1245 AssignmentOp::AssignAnd => Self::binary_result_type(
1246 BinaryOp::BooleanAnd,
1247 &left_resolved.ty,
1248 &right_resolved.ty,
1249 expr.span,
1250 )?,
1251 AssignmentOp::AssignXor => Self::binary_result_type(
1252 BinaryOp::ExclusiveOr,
1253 &left_resolved.ty,
1254 &right_resolved.ty,
1255 expr.span,
1256 )?,
1257 AssignmentOp::AssignOr => Self::binary_result_type(
1258 BinaryOp::InclusiveOr,
1259 &left_resolved.ty,
1260 &right_resolved.ty,
1261 expr.span,
1262 )?,
1263 AssignmentOp::AssignShiftLeft => Self::binary_result_type(
1264 BinaryOp::ShiftLeft,
1265 &left_resolved.ty,
1266 &right_resolved.ty,
1267 expr.span,
1268 )?,
1269 AssignmentOp::AssignShiftRight => Self::binary_result_type(
1270 BinaryOp::ShiftRight,
1271 &left_resolved.ty,
1272 &right_resolved.ty,
1273 expr.span,
1274 )?,
1275 AssignmentOp::AssignUnsignedShiftRight => Self::binary_result_type(
1276 BinaryOp::UnsignedShiftRight,
1277 &left_resolved.ty,
1278 &right_resolved.ty,
1279 expr.span,
1280 )?,
1281 };
1282
1283 if !types_compatible(&left_resolved.ty, &result_type) {
1284 return Err(SemanticError::new(
1285 CompilerErrorCode::MismatchedTypes,
1286 expr.span,
1287 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("assignment target has type {0:?}, expression has type {1:?}",
left_resolved.ty, result_type))
})format!(
1288 "assignment target has type {:?}, expression has type {:?}",
1289 left_resolved.ty, result_type
1290 ),
1291 ));
1292 }
1293
1294 Ok(ResolvedExpr {
1295 ty: left_resolved.ty,
1296 is_lvalue: false,
1297 is_const: false,
1298 })
1299 }
1300 }
1301 }
1302
1303 fn binary_result_type(
1304 op: BinaryOp,
1305 left: &SemanticType,
1306 right: &SemanticType,
1307 span: crate::Span,
1308 ) -> Result<SemanticType, SemanticError> {
1309 match op {
1310 BinaryOp::LogicalAnd
1311 | BinaryOp::LogicalOr
1312 | BinaryOp::InclusiveOr
1313 | BinaryOp::ExclusiveOr
1314 | BinaryOp::BooleanAnd => {
1315 if left == &SemanticType::Int && right == &SemanticType::Int {
1316 Ok(SemanticType::Int)
1317 } else {
1318 Err(SemanticError::new(
1319 CompilerErrorCode::LogicalOperationHasInvalidOperands,
1320 span,
1321 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("logical operation requires int operands, got {0:?} and {1:?}",
left, right))
})format!(
1322 "logical operation requires int operands, got {left:?} and {right:?}"
1323 ),
1324 ))
1325 }
1326 }
1327 BinaryOp::EqualEqual | BinaryOp::NotEqual => {
1328 if left == right
1329 && #[allow(non_exhaustive_omitted_patterns)] match left {
SemanticType::Int | SemanticType::Float | SemanticType::String |
SemanticType::Object | SemanticType::Vector | SemanticType::Struct(_)
| SemanticType::EngineStructure(_) => true,
_ => false,
}matches!(
1330 left,
1331 SemanticType::Int
1332 | SemanticType::Float
1333 | SemanticType::String
1334 | SemanticType::Object
1335 | SemanticType::Vector
1336 | SemanticType::Struct(_)
1337 | SemanticType::EngineStructure(_)
1338 )
1339 {
1340 Ok(SemanticType::Int)
1341 } else {
1342 Err(SemanticError::new(
1343 CompilerErrorCode::EqualityTestHasInvalidOperands,
1344 span,
1345 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("equality test requires matching operand types, got {0:?} and {1:?}",
left, right))
})format!(
1346 "equality test requires matching operand types, got {left:?} and \
1347 {right:?}"
1348 ),
1349 ))
1350 }
1351 }
1352 BinaryOp::GreaterEqual
1353 | BinaryOp::GreaterThan
1354 | BinaryOp::LessThan
1355 | BinaryOp::LessEqual => match (left, right) {
1356 (SemanticType::Int, SemanticType::Int)
1357 | (SemanticType::Float, SemanticType::Float) => Ok(SemanticType::Int),
1358 _ => Err(SemanticError::new(
1359 CompilerErrorCode::ComparisonTestHasInvalidOperands,
1360 span,
1361 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("comparison requires int/int or float/float operands, got {0:?} and {1:?}",
left, right))
})format!(
1362 "comparison requires int/int or float/float operands, got {left:?} and \
1363 {right:?}"
1364 ),
1365 )),
1366 },
1367 BinaryOp::ShiftLeft | BinaryOp::ShiftRight | BinaryOp::UnsignedShiftRight => {
1368 if left == &SemanticType::Int && right == &SemanticType::Int {
1369 Ok(SemanticType::Int)
1370 } else {
1371 Err(SemanticError::new(
1372 CompilerErrorCode::ShiftOperationHasInvalidOperands,
1373 span,
1374 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("shift operation requires int operands, got {0:?} and {1:?}",
left, right))
})format!(
1375 "shift operation requires int operands, got {left:?} and {right:?}"
1376 ),
1377 ))
1378 }
1379 }
1380 BinaryOp::Add | BinaryOp::Subtract | BinaryOp::Multiply | BinaryOp::Divide => {
1381 match (left, right) {
1382 (SemanticType::Int, SemanticType::Int) => Ok(SemanticType::Int),
1383 (SemanticType::Float, SemanticType::Int | SemanticType::Float)
1384 | (SemanticType::Int, SemanticType::Float) => Ok(SemanticType::Float),
1385 (SemanticType::String, SemanticType::String) if op == BinaryOp::Add => {
1386 Ok(SemanticType::String)
1387 }
1388 (SemanticType::Vector, SemanticType::Vector)
1389 if #[allow(non_exhaustive_omitted_patterns)] match op {
BinaryOp::Add | BinaryOp::Subtract => true,
_ => false,
}matches!(op, BinaryOp::Add | BinaryOp::Subtract) =>
1390 {
1391 Ok(SemanticType::Vector)
1392 }
1393 (SemanticType::Vector, SemanticType::Float)
1394 if #[allow(non_exhaustive_omitted_patterns)] match op {
BinaryOp::Multiply | BinaryOp::Divide => true,
_ => false,
}matches!(op, BinaryOp::Multiply | BinaryOp::Divide) =>
1395 {
1396 Ok(SemanticType::Vector)
1397 }
1398 (SemanticType::Float, SemanticType::Vector) if op == BinaryOp::Multiply => {
1399 Ok(SemanticType::Vector)
1400 }
1401 _ => Err(SemanticError::new(
1402 CompilerErrorCode::ArithmeticOperationHasInvalidOperands,
1403 span,
1404 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("arithmetic operation {0:?} is invalid for {1:?} and {2:?}",
op, left, right))
})format!(
1405 "arithmetic operation {op:?} is invalid for {left:?} and {right:?}"
1406 ),
1407 )),
1408 }
1409 }
1410 BinaryOp::Modulus => {
1411 if left == &SemanticType::Int && right == &SemanticType::Int {
1412 Ok(SemanticType::Int)
1413 } else {
1414 Err(SemanticError::new(
1415 CompilerErrorCode::ArithmeticOperationHasInvalidOperands,
1416 span,
1417 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("modulus requires int operands, got {0:?} and {1:?}",
left, right))
})format!("modulus requires int operands, got {left:?} and {right:?}"),
1418 ))
1419 }
1420 }
1421 }
1422 }
1423
1424 fn resolve_function_signature(
1425 &self,
1426 function: &FunctionDecl,
1427 ) -> Result<SemanticFunction, SemanticError> {
1428 let return_type = self.resolve_type(&function.return_type)?;
1429 let mut parameters = Vec::new();
1430 let mut optional_started = false;
1431 for parameter in &function.parameters {
1432 let parameter_type = self.resolve_type(¶meter.ty)?;
1433 let default = if let Some(default) = ¶meter.default {
1434 let value = self
1435 .evaluate_function_default_expr(default)
1436 .ok_or_else(|| {
1437 SemanticError::new(
1438 CompilerErrorCode::NonConstantInFunctionDeclaration,
1439 default.span,
1440 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("parameter {0:?} default value must be a constant",
parameter.name))
})format!(
1441 "parameter {:?} default value must be a constant",
1442 parameter.name
1443 ),
1444 )
1445 })?;
1446
1447 if !type_supports_optional_parameter(¶meter_type) {
1448 return Err(SemanticError::new(
1449 CompilerErrorCode::TypeDoesNotHaveAnOptionalParameter,
1450 default.span,
1451 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("type {0:?} does not support optional parameters",
parameter_type))
})format!("type {parameter_type:?} does not support optional parameters"),
1452 ));
1453 }
1454 if !types_compatible(¶meter_type, &value.ty()) {
1455 return Err(SemanticError::new(
1456 CompilerErrorCode::NonConstantInFunctionDeclaration,
1457 default.span,
1458 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("parameter {0:?} default type {1:?} does not match {2:?}",
parameter.name, value.ty(), parameter_type))
})format!(
1459 "parameter {:?} default type {:?} does not match {:?}",
1460 parameter.name,
1461 value.ty(),
1462 parameter_type
1463 ),
1464 ));
1465 }
1466 optional_started = true;
1467 Some(value)
1468 } else {
1469 if optional_started {
1470 return Err(SemanticError::new(
1471 CompilerErrorCode::NonOptionalParameterCannotFollowOptionalParameter,
1472 parameter.span,
1473 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("parameter {0:?} cannot follow an optional parameter",
parameter.name))
})format!(
1474 "parameter {:?} cannot follow an optional parameter",
1475 parameter.name
1476 ),
1477 ));
1478 }
1479 None
1480 };
1481
1482 parameters.push(SemanticParameter {
1483 name: parameter.name.clone(),
1484 ty: parameter_type,
1485 is_optional: default.is_some(),
1486 default: default.as_ref().map(literal_from_constant_value),
1487 });
1488 }
1489
1490 Ok(SemanticFunction {
1491 name: function.name.clone(),
1492 return_type,
1493 parameters,
1494 has_body: function.body.is_some(),
1495 is_builtin: false,
1496 })
1497 }
1498
1499 fn resolve_type(&self, ty: &TypeSpec) -> Result<SemanticType, SemanticError> {
1500 match &ty.kind {
1501 TypeKind::Void => Ok(SemanticType::Void),
1502 TypeKind::Int => Ok(SemanticType::Int),
1503 TypeKind::Float => Ok(SemanticType::Float),
1504 TypeKind::String => Ok(SemanticType::String),
1505 TypeKind::Object => Ok(SemanticType::Object),
1506 TypeKind::Vector => Ok(SemanticType::Vector),
1507 TypeKind::Struct(name) => {
1508 if !self.structs.contains_key(name) && name != "vector" {
1509 return Err(SemanticError::new(
1510 CompilerErrorCode::UndefinedStructure,
1511 ty.span,
1512 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("undefined structure {0:?}", name))
})format!("undefined structure {name:?}"),
1513 ));
1514 }
1515 if name == "vector" {
1516 Ok(SemanticType::Vector)
1517 } else {
1518 Ok(SemanticType::Struct(name.clone()))
1519 }
1520 }
1521 TypeKind::EngineStructure(name) => Ok(SemanticType::EngineStructure(name.clone())),
1522 }
1523 }
1524
1525 fn evaluate_constant_expr(&self, expr: &Expr) -> Option<ConstantValue> {
1526 match &expr.kind {
1527 ExprKind::Literal(literal) => constant_from_literal(literal),
1528 ExprKind::Identifier(name) => self.lookup_constant(name),
1529 ExprKind::Unary {
1530 op: UnaryOp::Negate,
1531 expr,
1532 } => {
1533 let value = self.evaluate_constant_expr(expr)?;
1534 match value {
1535 ConstantValue::Int(value) => Some(ConstantValue::Int(value.wrapping_neg())),
1536 ConstantValue::Float(value) => Some(ConstantValue::Float(-value)),
1537 _ => None,
1538 }
1539 }
1540 ExprKind::Unary {
1541 op: UnaryOp::BooleanNot,
1542 expr,
1543 } => match self.evaluate_constant_expr(expr)? {
1544 ConstantValue::Int(value) => Some(ConstantValue::Int(i32::from(value == 0))),
1545 _ => None,
1546 },
1547 ExprKind::Unary {
1548 op: UnaryOp::OnesComplement,
1549 expr,
1550 } => match self.evaluate_constant_expr(expr)? {
1551 ConstantValue::Int(value) => Some(ConstantValue::Int(!value)),
1552 _ => None,
1553 },
1554 ExprKind::Binary {
1555 op,
1556 left,
1557 right,
1558 } => self.evaluate_constant_binary(*op, left, right),
1559 ExprKind::Conditional {
1560 condition,
1561 when_true,
1562 when_false,
1563 } => {
1564 let condition = self.evaluate_constant_expr(condition)?;
1565 let take_true = match condition {
1566 ConstantValue::Int(value) => value != 0,
1567 _ => return None,
1568 };
1569 if take_true {
1570 self.evaluate_constant_expr(when_true)
1571 } else {
1572 self.evaluate_constant_expr(when_false)
1573 }
1574 }
1575 _ => None,
1576 }
1577 }
1578
1579 fn evaluate_function_default_expr(&self, expr: &Expr) -> Option<ConstantValue> {
1580 self.evaluate_constant_expr(expr)
1581 }
1582
1583 fn evaluate_constant_binary(
1584 &self,
1585 op: BinaryOp,
1586 left: &Expr,
1587 right: &Expr,
1588 ) -> Option<ConstantValue> {
1589 if #[allow(non_exhaustive_omitted_patterns)] match op {
BinaryOp::LogicalOr | BinaryOp::LogicalAnd => true,
_ => false,
}matches!(op, BinaryOp::LogicalOr | BinaryOp::LogicalAnd)
1590 && let Some(ConstantValue::Int(left_value)) = self.evaluate_constant_expr(left)
1591 {
1592 if op == BinaryOp::LogicalOr && left_value != 0 {
1593 return Some(ConstantValue::Int(1));
1594 }
1595 if op == BinaryOp::LogicalAnd && left_value == 0 {
1596 return Some(ConstantValue::Int(0));
1597 }
1598 }
1599
1600 let left = self.evaluate_constant_expr(left)?;
1601 let right = self.evaluate_constant_expr(right)?;
1602
1603 match (left, right) {
1604 (ConstantValue::Int(left), ConstantValue::Int(right)) => {
1605 evaluate_int_constant_binary(op, left, right).map(ConstantValue::Int)
1606 }
1607 (ConstantValue::Float(left), ConstantValue::Float(right)) => {
1608 evaluate_float_constant_binary(op, left, right)
1609 }
1610 (ConstantValue::String(left), ConstantValue::String(right)) => {
1611 evaluate_string_constant_binary(op, &left, &right)
1612 }
1613 _ => None,
1614 }
1615 }
1616
1617 fn evaluate_switch_case_value(&self, expr: &Expr) -> Option<i32> {
1618 match self.evaluate_constant_expr(expr)? {
1619 ConstantValue::Int(value) => Some(value),
1620 ConstantValue::String(value) => Some(nwscript_string_hash(&value)),
1621 _ => None,
1622 }
1623 }
1624
1625 fn lookup_constant(&self, name: &str) -> Option<ConstantValue> {
1626 self.global_constants
1627 .get(name)
1628 .cloned()
1629 .or_else(|| self.builtin_constants.get(name).cloned())
1630 }
1631
1632 fn lookup_value(
1633 &self,
1634 name: &str,
1635 scopes: &[BTreeMap<String, ScopeBinding>],
1636 ) -> Option<ValueBinding> {
1637 for scope in scopes.iter().rev() {
1638 if let Some(binding) = scope.get(name) {
1639 return Some(ValueBinding::Variable {
1640 ty: binding.ty.clone(),
1641 is_const: binding.is_const,
1642 });
1643 }
1644 }
1645
1646 if let Some(global) = self.globals.get(name) {
1647 if global.is_const
1648 && let Some(value) = self.global_constants.get(name).cloned()
1649 {
1650 return Some(ValueBinding::Constant(value));
1651 }
1652
1653 return Some(ValueBinding::Variable {
1654 ty: global.ty.clone(),
1655 is_const: global.is_const,
1656 });
1657 }
1658
1659 self.lookup_constant(name).map(ValueBinding::Constant)
1660 }
1661
1662 fn validate_entrypoint(&self) -> Result<(), SemanticError> {
1663 if !self.options.require_entrypoint {
1664 return Ok(());
1665 }
1666
1667 if let Some(main) = self.functions.get("main") {
1668 if main.signature.return_type != SemanticType::Void {
1669 return Err(SemanticError::new(
1670 CompilerErrorCode::FunctionMainMustHaveVoidReturnValue,
1671 main.declaration_span,
1672 "main must return void",
1673 ));
1674 }
1675 if !main.signature.parameters.is_empty() {
1676 return Err(SemanticError::new(
1677 CompilerErrorCode::FunctionMainMustHaveNoParameters,
1678 main.declaration_span,
1679 "main must not take parameters",
1680 ));
1681 }
1682 return Ok(());
1683 }
1684
1685 if self.options.allow_conditional_script {
1686 if let Some(function) = self.functions.get("StartingConditional") {
1687 if function.signature.return_type != SemanticType::Int {
1688 return Err(SemanticError::new(
1689 CompilerErrorCode::FunctionIntscMustHaveVoidReturnValue,
1690 function.declaration_span,
1691 "StartingConditional must return int",
1692 ));
1693 }
1694 if !function.signature.parameters.is_empty() {
1695 return Err(SemanticError::new(
1696 CompilerErrorCode::FunctionIntscMustHaveNoParameters,
1697 function.declaration_span,
1698 "StartingConditional must not take parameters",
1699 ));
1700 }
1701 return Ok(());
1702 }
1703 return Err(SemanticError::new(
1704 CompilerErrorCode::NoFunctionIntscInScript,
1705 crate::Span::new(crate::SourceId::new(0), 0, 0),
1706 "script must define StartingConditional",
1707 ));
1708 }
1709
1710 Err(SemanticError::new(
1711 CompilerErrorCode::NoFunctionMainInScript,
1712 crate::Span::new(crate::SourceId::new(0), 0, 0),
1713 "script must define main",
1714 ))
1715 }
1716}
1717
1718#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ResolvedExpr {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "ResolvedExpr",
"ty", &self.ty, "is_lvalue", &self.is_lvalue, "is_const",
&&self.is_const)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ResolvedExpr {
#[inline]
fn clone(&self) -> ResolvedExpr {
ResolvedExpr {
ty: ::core::clone::Clone::clone(&self.ty),
is_lvalue: ::core::clone::Clone::clone(&self.is_lvalue),
is_const: ::core::clone::Clone::clone(&self.is_const),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ResolvedExpr {
#[inline]
fn eq(&self, other: &ResolvedExpr) -> bool {
self.is_lvalue == other.is_lvalue && self.is_const == other.is_const
&& self.ty == other.ty
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ResolvedExpr {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<SemanticType>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq)]
1719struct ResolvedExpr {
1720 ty: SemanticType,
1721 is_lvalue: bool,
1722 is_const: bool,
1723}
1724
1725fn semantic_type_from_builtin_type(ty: &BuiltinType) -> SemanticType {
1726 match ty {
1727 BuiltinType::Int => SemanticType::Int,
1728 BuiltinType::Float => SemanticType::Float,
1729 BuiltinType::String => SemanticType::String,
1730 BuiltinType::Object => SemanticType::Object,
1731 BuiltinType::Void => SemanticType::Void,
1732 BuiltinType::Action => SemanticType::Action,
1733 BuiltinType::Vector => SemanticType::Vector,
1734 BuiltinType::EngineStructure(name) => SemanticType::EngineStructure(name.clone()),
1735 }
1736}
1737
1738fn constant_from_builtin_value(value: &BuiltinValue) -> Option<ConstantValue> {
1739 match value {
1740 BuiltinValue::Int(value) => Some(ConstantValue::Int(*value)),
1741 BuiltinValue::Float(value) => Some(ConstantValue::Float(*value)),
1742 BuiltinValue::String(value) => Some(ConstantValue::String(value.clone())),
1743 BuiltinValue::ObjectId(value) => Some(ConstantValue::ObjectId(*value)),
1744 BuiltinValue::ObjectSelf => Some(ConstantValue::ObjectSelf),
1745 BuiltinValue::ObjectInvalid => Some(ConstantValue::ObjectInvalid),
1746 BuiltinValue::LocationInvalid => Some(ConstantValue::LocationInvalid),
1747 BuiltinValue::Json(value) => Some(ConstantValue::Json(value.clone())),
1748 BuiltinValue::Vector(value) => Some(ConstantValue::Vector(*value)),
1749 BuiltinValue::Raw(_) => None,
1750 }
1751}
1752
1753fn literal_from_builtin_value(value: &BuiltinValue) -> Option<Literal> {
1754 constant_from_builtin_value(value).map(|value| literal_from_constant_value(&value))
1755}
1756
1757fn constant_from_literal(literal: &Literal) -> Option<ConstantValue> {
1758 match literal {
1759 Literal::Integer(value) => Some(ConstantValue::Int(*value)),
1760 Literal::Float(value) => Some(ConstantValue::Float(*value)),
1761 Literal::String(value) => Some(ConstantValue::String(value.clone())),
1762 Literal::ObjectSelf => Some(ConstantValue::ObjectSelf),
1763 Literal::ObjectInvalid => Some(ConstantValue::ObjectInvalid),
1764 Literal::LocationInvalid => Some(ConstantValue::LocationInvalid),
1765 Literal::Json(value) => Some(ConstantValue::Json(value.clone())),
1766 Literal::Vector(value) => Some(ConstantValue::Vector(*value)),
1767 Literal::Magic(
1768 MagicLiteral::Function
1769 | MagicLiteral::File
1770 | MagicLiteral::Line
1771 | MagicLiteral::Date
1772 | MagicLiteral::Time,
1773 ) => None,
1774 }
1775}
1776
1777fn literal_from_constant_value(value: &ConstantValue) -> Literal {
1778 match value {
1779 ConstantValue::Int(value) | ConstantValue::ObjectId(value) => Literal::Integer(*value),
1780 ConstantValue::Float(value) => Literal::Float(*value),
1781 ConstantValue::String(value) => Literal::String(value.clone()),
1782 ConstantValue::ObjectSelf => Literal::ObjectSelf,
1783 ConstantValue::ObjectInvalid => Literal::ObjectInvalid,
1784 ConstantValue::LocationInvalid => Literal::LocationInvalid,
1785 ConstantValue::Json(value) => Literal::Json(value.clone()),
1786 ConstantValue::Vector(value) => Literal::Vector(*value),
1787 }
1788}
1789
1790fn semantic_type_from_literal(literal: &Literal) -> SemanticType {
1791 match literal {
1792 Literal::Integer(_) | Literal::Magic(MagicLiteral::Line) => SemanticType::Int,
1793 Literal::Float(_) => SemanticType::Float,
1794 Literal::String(_)
1795 | Literal::Magic(
1796 MagicLiteral::Function | MagicLiteral::File | MagicLiteral::Date | MagicLiteral::Time,
1797 ) => SemanticType::String,
1798 Literal::ObjectSelf | Literal::ObjectInvalid => SemanticType::Object,
1799 Literal::LocationInvalid => SemanticType::EngineStructure("location".to_string()),
1800 Literal::Json(_) => SemanticType::EngineStructure("json".to_string()),
1801 Literal::Vector(_) => SemanticType::Vector,
1802 }
1803}
1804
1805fn default_constant_value(ty: &SemanticType) -> Option<ConstantValue> {
1806 match ty {
1807 SemanticType::Int => Some(ConstantValue::Int(0)),
1808 SemanticType::Float => Some(ConstantValue::Float(0.0)),
1809 SemanticType::String => Some(ConstantValue::String(String::new())),
1810 _ => None,
1811 }
1812}
1813
1814fn evaluate_int_constant_binary(op: BinaryOp, left: i32, right: i32) -> Option<i32> {
1815 match op {
1816 BinaryOp::LogicalOr => Some(i32::from(left != 0 || right != 0)),
1817 BinaryOp::LogicalAnd => Some(i32::from(left != 0 && right != 0)),
1818 BinaryOp::InclusiveOr => Some(left | right),
1819 BinaryOp::ExclusiveOr => Some(left ^ right),
1820 BinaryOp::BooleanAnd => Some(left & right),
1821 BinaryOp::EqualEqual => Some(i32::from(left == right)),
1822 BinaryOp::NotEqual => Some(i32::from(left != right)),
1823 BinaryOp::GreaterEqual => Some(i32::from(left >= right)),
1824 BinaryOp::GreaterThan => Some(i32::from(left > right)),
1825 BinaryOp::LessThan => Some(i32::from(left < right)),
1826 BinaryOp::LessEqual => Some(i32::from(left <= right)),
1827 BinaryOp::ShiftLeft => Some(left.wrapping_shl(right.cast_unsigned())),
1828 BinaryOp::ShiftRight => Some(left.wrapping_shr(right.cast_unsigned())),
1829 BinaryOp::UnsignedShiftRight => {
1830 Some(((left.cast_unsigned()).wrapping_shr(right.cast_unsigned())).cast_signed())
1831 }
1832 BinaryOp::Add => Some(left.wrapping_add(right)),
1833 BinaryOp::Subtract => Some(left.wrapping_sub(right)),
1834 BinaryOp::Multiply => Some(left.wrapping_mul(right)),
1835 BinaryOp::Divide => left.checked_div(right),
1836 BinaryOp::Modulus => left.checked_rem(right),
1837 }
1838}
1839
1840#[allow(clippy::float_cmp)]
1841fn evaluate_float_constant_binary(op: BinaryOp, left: f32, right: f32) -> Option<ConstantValue> {
1842 match op {
1843 BinaryOp::Add => Some(ConstantValue::Float(left + right)),
1844 BinaryOp::Subtract => Some(ConstantValue::Float(left - right)),
1845 BinaryOp::Multiply => Some(ConstantValue::Float(left * right)),
1846 BinaryOp::Divide => Some(ConstantValue::Float(left / right)),
1847 BinaryOp::EqualEqual => Some(ConstantValue::Int(i32::from(left == right))),
1848 BinaryOp::NotEqual => Some(ConstantValue::Int(i32::from(left != right))),
1849 BinaryOp::GreaterEqual => Some(ConstantValue::Int(i32::from(left >= right))),
1850 BinaryOp::GreaterThan => Some(ConstantValue::Int(i32::from(left > right))),
1851 BinaryOp::LessThan => Some(ConstantValue::Int(i32::from(left < right))),
1852 BinaryOp::LessEqual => Some(ConstantValue::Int(i32::from(left <= right))),
1853 _ => None,
1854 }
1855}
1856
1857fn evaluate_string_constant_binary(op: BinaryOp, left: &str, right: &str) -> Option<ConstantValue> {
1858 match op {
1859 BinaryOp::Add => {
1860 if left.len().saturating_add(right.len()) >= 0x8000 {
1861 None
1862 } else {
1863 Some(ConstantValue::String(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", left, right))
})format!("{left}{right}")))
1864 }
1865 }
1866 BinaryOp::EqualEqual => Some(ConstantValue::Int(i32::from(left == right))),
1867 BinaryOp::NotEqual => Some(ConstantValue::Int(i32::from(left != right))),
1868 _ => None,
1869 }
1870}
1871
1872fn type_supports_optional_parameter(ty: &SemanticType) -> bool {
1873 match ty {
1874 SemanticType::Int
1875 | SemanticType::Float
1876 | SemanticType::String
1877 | SemanticType::Object
1878 | SemanticType::Vector => true,
1879 SemanticType::EngineStructure(name) => name == "location" || name == "json",
1880 _ => false,
1881 }
1882}
1883
1884fn types_compatible(expected: &SemanticType, actual: &SemanticType) -> bool {
1885 expected == actual
1886}
1887
1888fn parameters_match(left: &[SemanticParameter], right: &[SemanticParameter]) -> bool {
1889 left.len() == right.len()
1890 && left
1891 .iter()
1892 .zip(right)
1893 .all(|(left, right)| left.ty == right.ty)
1894}
1895
1896fn insert_scope_binding(
1897 scopes: &mut [BTreeMap<String, ScopeBinding>],
1898 name: &str,
1899 ty: SemanticType,
1900 is_const: bool,
1901 span: crate::Span,
1902) -> Result<(), SemanticError> {
1903 if current_scope_contains(scopes, name) {
1904 return Err(SemanticError::new(
1905 CompilerErrorCode::VariableAlreadyUsedWithinScope,
1906 span,
1907 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("variable {0:?} was already declared in this scope",
name))
})format!("variable {name:?} was already declared in this scope"),
1908 ));
1909 }
1910
1911 let Some(scope) = scopes.last_mut() else {
1912 return Err(SemanticError::new(
1913 CompilerErrorCode::UnknownStateInCompiler,
1914 span,
1915 "scope stack must be non-empty",
1916 ));
1917 };
1918 scope.insert(
1919 name.to_string(),
1920 ScopeBinding {
1921 ty,
1922 is_const,
1923 },
1924 );
1925 Ok(())
1926}
1927
1928fn current_scope_contains(scopes: &[BTreeMap<String, ScopeBinding>], name: &str) -> bool {
1929 scopes.last().is_some_and(|scope| scope.contains_key(name))
1930}
1931
1932fn statement_guarantees_return(statement: &Stmt) -> bool {
1933 match statement {
1934 Stmt::Return(_) => true,
1935 Stmt::Block(block) => {
1936 for statement in &block.statements {
1937 if statement_guarantees_return(statement) {
1938 return true;
1939 }
1940 }
1941 false
1942 }
1943 Stmt::If(statement) => match &statement.else_branch {
1944 Some(else_branch) => {
1945 statement_guarantees_return(&statement.then_branch)
1946 && statement_guarantees_return(else_branch)
1947 }
1948 None => false,
1949 },
1950 _ => false,
1951 }
1952}
1953
1954#[cfg(test)]
1955mod tests {
1956 use super::{SemanticType, analyze_script, analyze_script_with_options};
1957 use crate::{LangSpec, Literal, SemanticOptions, SourceId, parse_text};
1958
1959 fn test_langspec() -> LangSpec {
1960 LangSpec {
1961 engine_num_structures: 3,
1962 engine_structures: vec![
1963 "effect".to_string(),
1964 "location".to_string(),
1965 "json".to_string(),
1966 ],
1967 constants: vec![
1968 crate::BuiltinConstant {
1969 name: "TRUE".to_string(),
1970 ty: crate::BuiltinType::Int,
1971 value: crate::BuiltinValue::Int(1),
1972 },
1973 crate::BuiltinConstant {
1974 name: "FALSE".to_string(),
1975 ty: crate::BuiltinType::Int,
1976 value: crate::BuiltinValue::Int(0),
1977 },
1978 crate::BuiltinConstant {
1979 name: "OBJECT_INVALID".to_string(),
1980 ty: crate::BuiltinType::Object,
1981 value: crate::BuiltinValue::ObjectInvalid,
1982 },
1983 ],
1984 functions: vec![
1985 crate::BuiltinFunction {
1986 name: "DelayCommand".to_string(),
1987 return_type: crate::BuiltinType::Void,
1988 parameters: vec![
1989 crate::BuiltinParameter {
1990 name: "fSeconds".to_string(),
1991 ty: crate::BuiltinType::Float,
1992 default: None,
1993 },
1994 crate::BuiltinParameter {
1995 name: "aAction".to_string(),
1996 ty: crate::BuiltinType::Action,
1997 default: None,
1998 },
1999 ],
2000 },
2001 crate::BuiltinFunction {
2002 name: "EffectDamage".to_string(),
2003 return_type: crate::BuiltinType::EngineStructure("effect".to_string()),
2004 parameters: vec![crate::BuiltinParameter {
2005 name: "nAmount".to_string(),
2006 ty: crate::BuiltinType::Int,
2007 default: None,
2008 }],
2009 },
2010 ],
2011 }
2012 }
2013
2014 #[test]
2015 fn resolves_functions_globals_and_structs() -> Result<(), Box<dyn std::error::Error>> {
2016 let script = parse_text(
2017 SourceId::new(40),
2018 "struct Foo { int value; }; effect gFx; void helper(int n = TRUE); void helper(int n \
2019 = TRUE) { int x = n; } void main() { struct Foo f; int x = f.value; }",
2020 Some(&test_langspec()),
2021 )?;
2022
2023 let model = analyze_script(&script, Some(&test_langspec()))?;
2024 assert!(model.structs.contains_key("Foo"));
2025 assert!(model.functions.contains_key("helper"));
2026 assert!(model.functions.contains_key("EffectDamage"));
2027 assert_eq!(
2028 model
2029 .globals
2030 .get("gFx")
2031 .ok_or_else(|| std::io::Error::other("missing global gFx"))?
2032 .ty,
2033 SemanticType::EngineStructure("effect".to_string())
2034 );
2035 Ok(())
2036 }
2037
2038 #[test]
2039 fn rejects_optional_parameter_ordering() {
2040 let script = parse_text(
2041 SourceId::new(41),
2042 "void helper(int n = 1, int m); void main() { return; }",
2043 Some(&test_langspec()),
2044 )
2045 .expect("script should parse");
2046
2047 let error =
2048 analyze_script(&script, Some(&test_langspec())).expect_err("analysis should fail");
2049 assert_eq!(
2050 error.code,
2051 crate::CompilerErrorCode::NonOptionalParameterCannotFollowOptionalParameter
2052 );
2053 }
2054
2055 #[test]
2056 fn folds_constant_globals_and_uses_default_constant_values()
2057 -> Result<(), Box<dyn std::error::Error>> {
2058 let script = parse_text(
2059 SourceId::new(46),
2060 r#"
2061 const int MASK = (1 + 2) * 4;
2062 const int ZERO;
2063 const string LABEL = "ab" + "cd";
2064 const int PICK = TRUE ? 7 : 9;
2065 void main() {
2066 int x = MASK;
2067 int y = ZERO;
2068 string s = LABEL;
2069 int z = PICK;
2070 }
2071 "#,
2072 Some(&test_langspec()),
2073 )?;
2074
2075 let model = analyze_script(&script, Some(&test_langspec()))?;
2076 assert_eq!(
2077 model.globals.get("MASK").map(|global| global.is_const),
2078 Some(true)
2079 );
2080 assert_eq!(
2081 model.globals.get("ZERO").map(|global| global.is_const),
2082 Some(true)
2083 );
2084 assert_eq!(
2085 model.globals.get("LABEL").map(|global| global.is_const),
2086 Some(true)
2087 );
2088 assert_eq!(
2089 model.globals.get("PICK").map(|global| global.is_const),
2090 Some(true)
2091 );
2092 Ok(())
2093 }
2094
2095 #[test]
2096 fn accepts_case_labels_backed_by_const_globals() {
2097 let script = parse_text(
2098 SourceId::new(47),
2099 r#"
2100 const int CASE_A = 1 + 2;
2101 const int CASE_B = FALSE ? 8 : 4;
2102 void main() {
2103 int n = 0;
2104 switch (n) {
2105 case CASE_A:
2106 break;
2107 case CASE_B:
2108 break;
2109 default:
2110 break;
2111 }
2112 }
2113 "#,
2114 Some(&test_langspec()),
2115 )
2116 .expect("script should parse");
2117
2118 analyze_script(&script, Some(&test_langspec()))
2119 .expect("const global should be valid in case label");
2120 }
2121
2122 #[test]
2123 fn accepts_function_defaults_backed_by_const_globals_and_expressions() {
2124 let script = parse_text(
2125 SourceId::new(48),
2126 r#"
2127 const int EXECUTE_END = 1;
2128 const int POLICY_DEFAULT = EXECUTE_END + 2;
2129 void helper(int nValue = EXECUTE_END, int nPolicy = POLICY_DEFAULT) {
2130 return;
2131 }
2132 void main() {
2133 helper();
2134 }
2135 "#,
2136 Some(&test_langspec()),
2137 )
2138 .expect("script should parse");
2139
2140 analyze_script(&script, Some(&test_langspec()))
2141 .expect("const global defaults should resolve in function signatures");
2142 }
2143
2144 #[test]
2145 fn accepts_string_case_labels_by_upstream_hash_rule() {
2146 let script = parse_text(
2147 SourceId::new(49),
2148 r#"
2149 const string LABEL = "abc";
2150 void main() {
2151 int n = 0;
2152 switch (n) {
2153 case "abc":
2154 break;
2155 case LABEL:
2156 break;
2157 }
2158 }
2159 "#,
2160 Some(&test_langspec()),
2161 )
2162 .expect("script should parse");
2163
2164 let error =
2165 analyze_script(&script, Some(&test_langspec())).expect_err("analysis should fail");
2166 assert_eq!(
2167 error.code,
2168 crate::CompilerErrorCode::MultipleCaseConstantStatementsWithinSwitch
2169 );
2170 }
2171
2172 #[test]
2173 fn rejects_duplicate_default_labels_within_one_switch() {
2174 let script = parse_text(
2175 SourceId::new(50),
2176 r#"
2177 void main() {
2178 int n = 0;
2179 switch (n) {
2180 default:
2181 break;
2182 default:
2183 break;
2184 }
2185 }
2186 "#,
2187 Some(&test_langspec()),
2188 )
2189 .expect("script should parse");
2190
2191 let error =
2192 analyze_script(&script, Some(&test_langspec())).expect_err("analysis should fail");
2193 assert_eq!(
2194 error.code,
2195 crate::CompilerErrorCode::MultipleDefaultStatementsWithinSwitch
2196 );
2197 }
2198
2199 #[test]
2200 fn rejects_case_and_default_labels_that_jump_over_live_declarations() {
2201 let case_script = parse_text(
2202 SourceId::new(51),
2203 r#"
2204 void main() {
2205 int n = 0;
2206 switch (n) {
2207 int x = 1;
2208 case 1:
2209 break;
2210 }
2211 }
2212 "#,
2213 Some(&test_langspec()),
2214 )
2215 .expect("script should parse");
2216
2217 let case_error =
2218 analyze_script(&case_script, Some(&test_langspec())).expect_err("analysis should fail");
2219 assert_eq!(
2220 case_error.code,
2221 crate::CompilerErrorCode::JumpingOverDeclarationStatementsCaseDisallowed
2222 );
2223
2224 let default_script = parse_text(
2225 SourceId::new(52),
2226 r#"
2227 void main() {
2228 int n = 0;
2229 switch (n) {
2230 int x = 1;
2231 default:
2232 break;
2233 }
2234 }
2235 "#,
2236 Some(&test_langspec()),
2237 )
2238 .expect("script should parse");
2239
2240 let default_error = analyze_script(&default_script, Some(&test_langspec()))
2241 .expect_err("analysis should fail");
2242 assert_eq!(
2243 default_error.code,
2244 crate::CompilerErrorCode::JumpingOverDeclarationStatementsDefaultDisallowed
2245 );
2246 }
2247
2248 #[test]
2249 fn duplicate_case_detection_is_scoped_to_the_innermost_switch() {
2250 let script = parse_text(
2251 SourceId::new(53),
2252 r#"
2253 void main() {
2254 int n = 0;
2255 switch (n) {
2256 case 1:
2257 switch (n) {
2258 case 1:
2259 break;
2260 default:
2261 break;
2262 }
2263 break;
2264 default:
2265 break;
2266 }
2267 }
2268 "#,
2269 Some(&test_langspec()),
2270 )
2271 .expect("script should parse");
2272
2273 analyze_script(&script, Some(&test_langspec()))
2274 .expect("nested switch labels should be tracked independently");
2275 }
2276
2277 #[test]
2278 fn parser_accepts_constant_function_default_expressions_like_upstream() {
2279 let script = parse_text(
2280 SourceId::new(48),
2281 "void helper(int n = 1 + 2); void main() {}",
2282 Some(&test_langspec()),
2283 )
2284 .expect("parser should accept constant default expressions");
2285
2286 analyze_script(&script, Some(&test_langspec()))
2287 .expect("semantic analysis should accept constant default expressions");
2288 }
2289
2290 #[test]
2291 fn rejects_undefined_identifiers_and_bad_field_access() {
2292 let script = parse_text(
2293 SourceId::new(42),
2294 "struct Foo { int value; }; void main() { struct Foo f; int x = f.missing; }",
2295 Some(&test_langspec()),
2296 )
2297 .expect("script should parse");
2298
2299 let error =
2300 analyze_script(&script, Some(&test_langspec())).expect_err("analysis should fail");
2301 assert!(matches!(
2302 error.code,
2303 crate::CompilerErrorCode::UndefinedFieldInStructure
2304 | crate::CompilerErrorCode::UndefinedIdentifier
2305 ));
2306 }
2307
2308 #[test]
2309 fn action_parameters_require_direct_void_calls() {
2310 let valid = parse_text(
2311 SourceId::new(54),
2312 "void helper() {} void main() { DelayCommand(1.0, helper()); }",
2313 Some(&test_langspec()),
2314 )
2315 .expect("script should parse");
2316 analyze_script(&valid, Some(&test_langspec()))
2317 .expect("void call should be valid for action parameter");
2318
2319 let invalid = parse_text(
2320 SourceId::new(55),
2321 "void main() { DelayCommand(1.0, EffectDamage(1)); }",
2322 Some(&test_langspec()),
2323 )
2324 .expect("script should parse");
2325 let error =
2326 analyze_script(&invalid, Some(&test_langspec())).expect_err("analysis should fail");
2327 assert_eq!(
2328 error.code,
2329 crate::CompilerErrorCode::DeclarationDoesNotMatchParameters
2330 );
2331 }
2332
2333 #[test]
2334 fn function_name_reuse_requires_identical_parameter_lists() {
2335 let mismatch = parse_text(
2336 SourceId::new(56),
2337 "void helper(int n); void helper(float n); void main() {}",
2338 Some(&test_langspec()),
2339 )
2340 .expect("script should parse");
2341 let mismatch_error =
2342 analyze_script(&mismatch, Some(&test_langspec())).expect_err("analysis should fail");
2343 assert_eq!(
2344 mismatch_error.code,
2345 crate::CompilerErrorCode::FunctionImplementationAndDefinitionDiffer
2346 );
2347
2348 let return_mismatch = parse_text(
2349 SourceId::new(65),
2350 "int helper(int n); void helper(int n) {} void main() {}",
2351 Some(&test_langspec()),
2352 )
2353 .expect("script should parse");
2354 let return_mismatch_error = analyze_script(&return_mismatch, Some(&test_langspec()))
2355 .expect_err("analysis should fail");
2356 assert_eq!(
2357 return_mismatch_error.code,
2358 crate::CompilerErrorCode::FunctionImplementationAndDefinitionDiffer
2359 );
2360
2361 let duplicate_impl = parse_text(
2362 SourceId::new(57),
2363 "void helper(int n) {} void helper(int n) {} void main() {}",
2364 Some(&test_langspec()),
2365 )
2366 .expect("script should parse");
2367 let duplicate_impl_error = analyze_script(&duplicate_impl, Some(&test_langspec()))
2368 .expect_err("analysis should fail");
2369 assert_eq!(
2370 duplicate_impl_error.code,
2371 crate::CompilerErrorCode::DuplicateFunctionImplementation
2372 );
2373 }
2374
2375 #[test]
2376 fn function_redeclarations_may_add_or_remove_trailing_defaults_like_upstream() {
2377 let later_default = parse_text(
2378 SourceId::new(60),
2379 "void helper(int n); void helper(int n = 1) {} void main() {}",
2380 Some(&test_langspec()),
2381 )
2382 .expect("script should parse");
2383 analyze_script(&later_default, Some(&test_langspec()))
2384 .expect("later implementation default should be accepted");
2385
2386 let earlier_default = parse_text(
2387 SourceId::new(61),
2388 "void helper(int n = 1); void helper(int n) {} void main() {}",
2389 Some(&test_langspec()),
2390 )
2391 .expect("script should parse");
2392 let earlier_default_semantic = analyze_script(&earlier_default, Some(&test_langspec()))
2393 .expect("later implementation without default should be accepted");
2394 let helper = earlier_default_semantic
2395 .functions
2396 .get("helper")
2397 .expect("helper should be present in the semantic model");
2398 let first_parameter = helper
2399 .parameters
2400 .first()
2401 .expect("helper should have one parameter");
2402 assert_eq!(
2403 first_parameter.default,
2404 Some(Literal::Integer(1)),
2405 "forward declaration defaults should survive into the merged signature"
2406 );
2407
2408 let renamed_parameter = parse_text(
2409 SourceId::new(64),
2410 "int helper(int nDurationType); int helper(int nDurationCompare) { return \
2411 nDurationCompare; } void main() {}",
2412 Some(&test_langspec()),
2413 )
2414 .expect("script should parse");
2415 analyze_script(&renamed_parameter, Some(&test_langspec()))
2416 .expect("implementation parameter names should be visible inside the body");
2417 }
2418
2419 #[test]
2420 fn nested_scopes_may_shadow_outer_names_but_same_scope_duplicates_fail() {
2421 let shadowing = parse_text(
2422 SourceId::new(62),
2423 "int g = 1; void main() { int x = g; { int x = 2; int y = x; } int z = x; }",
2424 Some(&test_langspec()),
2425 )
2426 .expect("script should parse");
2427 analyze_script(&shadowing, Some(&test_langspec()))
2428 .expect("nested scopes should be allowed to shadow outer names");
2429
2430 let duplicate = parse_text(
2431 SourceId::new(63),
2432 "void main() { int x = 1; int x = 2; }",
2433 Some(&test_langspec()),
2434 )
2435 .expect("script should parse");
2436 let duplicate_error =
2437 analyze_script(&duplicate, Some(&test_langspec())).expect_err("analysis should fail");
2438 assert_eq!(
2439 duplicate_error.code,
2440 crate::CompilerErrorCode::VariableAlreadyUsedWithinScope
2441 );
2442 }
2443
2444 #[test]
2445 fn function_body_scope_may_shadow_parameter_names() {
2446 let script = parse_text(
2447 SourceId::new(65),
2448 "int helper(object oSpellTarget) { object oSpellTarget = OBJECT_SELF; return TRUE; } \
2449 void main() {}",
2450 Some(&test_langspec()),
2451 )
2452 .expect("script should parse");
2453 analyze_script(&script, Some(&test_langspec()))
2454 .expect("function body locals should be allowed to shadow parameter names");
2455 }
2456
2457 #[test]
2458 fn rejects_local_const_declarations_like_upstream() {
2459 let script = parse_text(
2460 SourceId::new(43),
2461 "void main() { const int x = 1; }",
2462 Some(&test_langspec()),
2463 )
2464 .expect("script should parse");
2465
2466 let error =
2467 analyze_script(&script, Some(&test_langspec())).expect_err("analysis should fail");
2468 assert_eq!(
2469 error.code,
2470 crate::CompilerErrorCode::ConstKeywordCannotBeUsedOnNonGlobalVariables
2471 );
2472 }
2473
2474 #[test]
2475 fn rejects_missing_return_paths() {
2476 let script = parse_text(
2477 SourceId::new(44),
2478 "int main() { if (TRUE) { return 1; } }",
2479 Some(&test_langspec()),
2480 )
2481 .expect("script should parse");
2482
2483 let error =
2484 analyze_script(&script, Some(&test_langspec())).expect_err("analysis should fail");
2485 assert_eq!(
2486 error.code,
2487 crate::CompilerErrorCode::NotAllControlPathsReturnAValue
2488 );
2489 }
2490
2491 #[test]
2492 fn validates_required_entrypoints_when_requested() {
2493 let script = parse_text(
2494 SourceId::new(45),
2495 "int helper() { return 1; }",
2496 Some(&test_langspec()),
2497 )
2498 .expect("script should parse");
2499
2500 let error = analyze_script_with_options(
2501 &script,
2502 Some(&test_langspec()),
2503 SemanticOptions {
2504 require_entrypoint: true,
2505 allow_conditional_script: false,
2506 },
2507 )
2508 .expect_err("analysis should fail");
2509 assert_eq!(error.code, crate::CompilerErrorCode::NoFunctionMainInScript);
2510 }
2511}