#![warn(missing_docs)]
#![warn(clippy::all)]
#![deny(unsafe_code)]
#[macro_use]
#[allow(unused_macros)]
mod generated_contracts;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HirType {
Void,
Bool,
Int,
UnsignedInt,
Float,
Double,
Char,
SignedChar,
Pointer(Box<HirType>),
Box(Box<HirType>),
Vec(Box<HirType>),
Option(Box<HirType>),
Reference {
inner: Box<HirType>,
mutable: bool,
},
Struct(String),
Enum(String),
Union(Vec<(String, HirType)>),
Array {
element_type: Box<HirType>,
size: Option<usize>,
},
FunctionPointer {
param_types: Vec<HirType>,
return_type: Box<HirType>,
},
StringLiteral,
OwnedString,
StringReference,
TypeAlias(String),
}
impl HirType {
pub fn from_ast_type(ast_type: &decy_parser::parser::Type) -> Self {
contract_pre_parse!();
use decy_parser::parser::Type;
match ast_type {
Type::Void => HirType::Void,
Type::Bool => HirType::Bool,
Type::Int => HirType::Int,
Type::UnsignedInt => HirType::UnsignedInt, Type::Float => HirType::Float,
Type::Double => HirType::Double,
Type::Char => HirType::Char,
Type::SignedChar => HirType::SignedChar, Type::Pointer(inner) => HirType::Pointer(Box::new(HirType::from_ast_type(inner))),
Type::Struct(name) => HirType::Struct(name.clone()),
Type::FunctionPointer { param_types, return_type } => HirType::FunctionPointer {
param_types: param_types.iter().map(HirType::from_ast_type).collect(),
return_type: Box::new(HirType::from_ast_type(return_type)),
},
Type::Array { element_type, size } => HirType::Array {
element_type: Box::new(HirType::from_ast_type(element_type)),
size: size.map(|s| s as usize),
},
Type::TypeAlias(name) => HirType::TypeAlias(name.clone()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirStructField {
name: String,
field_type: HirType,
}
impl HirStructField {
pub fn new(name: String, field_type: HirType) -> Self {
Self { name, field_type }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn field_type(&self) -> &HirType {
&self.field_type
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirStruct {
name: String,
fields: Vec<HirStructField>,
}
impl HirStruct {
pub fn new(name: String, fields: Vec<HirStructField>) -> Self {
Self { name, fields }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn fields(&self) -> &[HirStructField] {
&self.fields
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HirCxxOperatorKind {
Add,
Sub,
Mul,
Div,
Rem,
Equal,
NotEqual,
Less,
Index,
AddAssign,
SubAssign,
}
#[derive(Debug, Clone, PartialEq)]
pub struct HirMethod {
function: HirFunction,
is_const: bool,
is_static: bool,
is_virtual: bool,
operator_kind: Option<HirCxxOperatorKind>,
}
impl HirMethod {
pub fn new(function: HirFunction, is_const: bool, is_static: bool, is_virtual: bool) -> Self {
Self { function, is_const, is_static, is_virtual, operator_kind: None }
}
pub fn function(&self) -> &HirFunction {
&self.function
}
pub fn is_const(&self) -> bool {
self.is_const
}
pub fn is_static(&self) -> bool {
self.is_static
}
pub fn is_virtual(&self) -> bool {
self.is_virtual
}
pub fn operator_kind(&self) -> Option<HirCxxOperatorKind> {
self.operator_kind
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct HirClass {
name: String,
fields: Vec<HirStructField>,
methods: Vec<HirMethod>,
constructor_params: Vec<HirParameter>,
has_destructor: bool,
base_class: Option<String>,
}
impl HirClass {
pub fn new(name: String) -> Self {
Self {
name,
fields: Vec::new(),
methods: Vec::new(),
constructor_params: Vec::new(),
has_destructor: false,
base_class: None,
}
}
pub fn from_ast_class(ast_class: &decy_parser::parser::Class) -> Self {
contract_pre_class_to_struct!();
let fields = ast_class
.fields
.iter()
.map(|f| HirStructField::new(f.name().to_string(), HirType::from_ast_type(&f.field_type)))
.collect();
let methods = ast_class
.methods
.iter()
.map(|m| {
let mut method = HirMethod::new(
HirFunction::from_ast_function(&m.function),
m.is_const,
m.is_static,
m.is_virtual,
);
method.operator_kind = m.operator_kind.map(|op| {
use decy_parser::parser::CxxOperatorKind as P;
match op {
P::Add => HirCxxOperatorKind::Add,
P::Sub => HirCxxOperatorKind::Sub,
P::Mul => HirCxxOperatorKind::Mul,
P::Div => HirCxxOperatorKind::Div,
P::Rem => HirCxxOperatorKind::Rem,
P::Equal | P::NotEqual => HirCxxOperatorKind::Equal,
P::Less | P::LessEqual | P::Greater | P::GreaterEqual => {
HirCxxOperatorKind::Less
}
P::Index => HirCxxOperatorKind::Index,
P::AddAssign => HirCxxOperatorKind::AddAssign,
P::SubAssign => HirCxxOperatorKind::SubAssign,
P::Shl | P::Shr => HirCxxOperatorKind::Add, }
});
method
})
.collect();
let constructor_params = ast_class
.constructor_params
.iter()
.map(HirParameter::from_ast_parameter)
.collect();
Self {
name: ast_class.name.clone(),
fields,
methods,
constructor_params,
has_destructor: ast_class.has_destructor,
base_class: ast_class.base_class.clone(),
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn fields(&self) -> &[HirStructField] {
&self.fields
}
pub fn methods(&self) -> &[HirMethod] {
&self.methods
}
pub fn constructor_params(&self) -> &[HirParameter] {
&self.constructor_params
}
pub fn has_destructor(&self) -> bool {
self.has_destructor
}
pub fn base_class(&self) -> Option<&str> {
self.base_class.as_deref()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct HirNamespace {
name: String,
functions: Vec<HirFunction>,
structs: Vec<HirStruct>,
classes: Vec<HirClass>,
namespaces: Vec<HirNamespace>,
}
impl HirNamespace {
pub fn new(name: String) -> Self {
Self {
name,
functions: Vec::new(),
structs: Vec::new(),
classes: Vec::new(),
namespaces: Vec::new(),
}
}
pub fn from_ast_namespace(ast_ns: &decy_parser::parser::Namespace) -> Self {
Self {
name: ast_ns.name.clone(),
functions: ast_ns.functions.iter().map(HirFunction::from_ast_function).collect(),
structs: ast_ns
.structs
.iter()
.map(|s| {
HirStruct::new(
s.name().to_string(),
s.fields()
.iter()
.map(|f| {
HirStructField::new(
f.name().to_string(),
HirType::from_ast_type(&f.field_type),
)
})
.collect(),
)
})
.collect(),
classes: ast_ns.classes.iter().map(HirClass::from_ast_class).collect(),
namespaces: ast_ns.namespaces.iter().map(HirNamespace::from_ast_namespace).collect(),
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn functions(&self) -> &[HirFunction] {
&self.functions
}
pub fn structs(&self) -> &[HirStruct] {
&self.structs
}
pub fn classes(&self) -> &[HirClass] {
&self.classes
}
pub fn namespaces(&self) -> &[HirNamespace] {
&self.namespaces
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirEnumVariant {
name: String,
value: Option<i32>,
}
impl HirEnumVariant {
pub fn new(name: String, value: Option<i32>) -> Self {
Self { name, value }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn value(&self) -> Option<i32> {
self.value
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirEnum {
name: String,
variants: Vec<HirEnumVariant>,
}
impl HirEnum {
pub fn new(name: String, variants: Vec<HirEnumVariant>) -> Self {
Self { name, variants }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn variants(&self) -> &[HirEnumVariant] {
&self.variants
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirTypedef {
name: String,
underlying_type: HirType,
}
impl HirTypedef {
pub fn new(name: String, underlying_type: HirType) -> Self {
Self { name, underlying_type }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn underlying_type(&self) -> &HirType {
&self.underlying_type
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct HirConstant {
name: String,
const_type: HirType,
value: HirExpression,
}
impl HirConstant {
pub fn new(name: String, const_type: HirType, value: HirExpression) -> Self {
Self { name, const_type, value }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn const_type(&self) -> &HirType {
&self.const_type
}
pub fn value(&self) -> &HirExpression {
&self.value
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirMacroDefinition {
name: String,
parameters: Vec<String>,
body: String,
}
impl HirMacroDefinition {
pub fn new_object_like(name: String, body: String) -> Self {
Self { name, parameters: vec![], body }
}
pub fn new_function_like(name: String, parameters: Vec<String>, body: String) -> Self {
Self { name, parameters, body }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn parameters(&self) -> &[String] {
&self.parameters
}
pub fn body(&self) -> &str {
&self.body
}
pub fn is_function_like(&self) -> bool {
!self.parameters.is_empty()
}
pub fn is_object_like(&self) -> bool {
self.parameters.is_empty()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HirParameter {
name: String,
param_type: HirType,
is_pointee_const: bool,
}
impl HirParameter {
pub fn new(name: String, param_type: HirType) -> Self {
Self { name, param_type, is_pointee_const: false }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn param_type(&self) -> &HirType {
&self.param_type
}
pub fn is_pointee_const(&self) -> bool {
self.is_pointee_const
}
pub fn is_const_char_pointer(&self) -> bool {
self.is_pointee_const
&& matches!(self.param_type, HirType::Pointer(ref inner) if **inner == HirType::Char)
}
pub fn from_ast_parameter(ast_param: &decy_parser::parser::Parameter) -> Self {
contract_pre_parse!();
Self {
name: ast_param.name.clone(),
param_type: HirType::from_ast_type(&ast_param.param_type),
is_pointee_const: ast_param.is_pointee_const,
}
}
pub fn with_type(&self, new_type: HirType) -> Self {
Self {
name: self.name.clone(),
param_type: new_type,
is_pointee_const: self.is_pointee_const,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HirCudaQualifier {
Global,
Device,
Host,
HostDevice,
}
#[derive(Debug, Clone, PartialEq)]
pub struct HirFunction {
name: String,
return_type: HirType,
parameters: Vec<HirParameter>,
body: Option<Vec<HirStatement>>,
cuda_qualifier: Option<HirCudaQualifier>,
}
impl HirFunction {
pub fn new(name: String, return_type: HirType, parameters: Vec<HirParameter>) -> Self {
Self { name, return_type, parameters, body: None, cuda_qualifier: None }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn return_type(&self) -> &HirType {
&self.return_type
}
pub fn parameters(&self) -> &[HirParameter] {
&self.parameters
}
pub fn from_ast_function(ast_func: &decy_parser::parser::Function) -> Self {
let body = if ast_func.body.is_empty() {
None
} else {
Some(ast_func.body.iter().map(HirStatement::from_ast_statement).collect())
};
let cuda_qualifier = ast_func.cuda_qualifier.map(|q| match q {
decy_parser::parser::CudaQualifier::Global => HirCudaQualifier::Global,
decy_parser::parser::CudaQualifier::Device => HirCudaQualifier::Device,
decy_parser::parser::CudaQualifier::Host => HirCudaQualifier::Host,
decy_parser::parser::CudaQualifier::HostDevice => HirCudaQualifier::HostDevice,
});
Self {
name: ast_func.name.clone(),
return_type: HirType::from_ast_type(&ast_func.return_type),
parameters: ast_func.parameters.iter().map(HirParameter::from_ast_parameter).collect(),
body,
cuda_qualifier,
}
}
pub fn new_with_body(
name: String,
return_type: HirType,
parameters: Vec<HirParameter>,
body: Vec<HirStatement>,
) -> Self {
Self { name, return_type, parameters, body: Some(body), cuda_qualifier: None }
}
pub fn body(&self) -> &[HirStatement] {
self.body.as_deref().unwrap_or(&[])
}
pub fn has_body(&self) -> bool {
self.body.is_some()
}
pub fn cuda_qualifier(&self) -> Option<HirCudaQualifier> {
self.cuda_qualifier
}
pub fn set_cuda_qualifier(&mut self, qualifier: Option<HirCudaQualifier>) {
contract_pre_qualifier_preservation!();
self.cuda_qualifier = qualifier;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOperator {
Minus,
LogicalNot,
BitwiseNot,
AddressOf,
PostIncrement,
PostDecrement,
PreIncrement,
PreDecrement,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOperator {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Equal,
NotEqual,
LessThan,
GreaterThan,
LessEqual,
GreaterEqual,
LogicalAnd,
LogicalOr,
LeftShift,
RightShift,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
Assign,
Comma,
}
#[derive(Debug, Clone, PartialEq)]
pub enum HirExpression {
IntLiteral(i32),
FloatLiteral(String),
StringLiteral(String),
CharLiteral(i8),
Variable(String),
BinaryOp {
op: BinaryOperator,
left: Box<HirExpression>,
right: Box<HirExpression>,
},
Dereference(Box<HirExpression>),
AddressOf(Box<HirExpression>),
UnaryOp {
op: UnaryOperator,
operand: Box<HirExpression>,
},
PostIncrement {
operand: Box<HirExpression>,
},
PreIncrement {
operand: Box<HirExpression>,
},
PostDecrement {
operand: Box<HirExpression>,
},
PreDecrement {
operand: Box<HirExpression>,
},
FunctionCall {
function: String,
arguments: Vec<HirExpression>,
},
FieldAccess {
object: Box<HirExpression>,
field: String,
},
PointerFieldAccess {
pointer: Box<HirExpression>,
field: String,
},
ArrayIndex {
array: Box<HirExpression>,
index: Box<HirExpression>,
},
SliceIndex {
slice: Box<HirExpression>,
index: Box<HirExpression>,
element_type: HirType,
},
Sizeof {
type_name: String,
},
NullLiteral,
IsNotNull(Box<HirExpression>),
Calloc {
count: Box<HirExpression>,
element_type: Box<HirType>,
},
Malloc {
size: Box<HirExpression>,
},
Realloc {
pointer: Box<HirExpression>,
new_size: Box<HirExpression>,
},
StringMethodCall {
receiver: Box<HirExpression>,
method: String,
arguments: Vec<HirExpression>,
},
Cast {
target_type: HirType,
expr: Box<HirExpression>,
},
CompoundLiteral {
literal_type: HirType,
initializers: Vec<HirExpression>,
},
Ternary {
condition: Box<HirExpression>,
then_expr: Box<HirExpression>,
else_expr: Box<HirExpression>,
},
CxxNew {
allocated_type: HirType,
arguments: Vec<HirExpression>,
},
CxxDelete {
operand: Box<HirExpression>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct SwitchCase {
pub value: Option<HirExpression>,
pub body: Vec<HirStatement>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum HirStatement {
VariableDeclaration {
name: String,
var_type: HirType,
initializer: Option<HirExpression>,
},
Return(Option<HirExpression>),
If {
condition: HirExpression,
then_block: Vec<HirStatement>,
else_block: Option<Vec<HirStatement>>,
},
While {
condition: HirExpression,
body: Vec<HirStatement>,
},
Break,
Continue,
Assignment {
target: String,
value: HirExpression,
},
For {
init: Vec<HirStatement>,
condition: Option<HirExpression>,
increment: Vec<HirStatement>,
body: Vec<HirStatement>,
},
Switch {
condition: HirExpression,
cases: Vec<SwitchCase>,
default_case: Option<Vec<HirStatement>>,
},
DerefAssignment {
target: HirExpression,
value: HirExpression,
},
ArrayIndexAssignment {
array: Box<HirExpression>,
index: Box<HirExpression>,
value: HirExpression,
},
FieldAssignment {
object: HirExpression,
field: String,
value: HirExpression,
},
Free {
pointer: HirExpression,
},
Expression(HirExpression),
InlineAsm {
text: String,
translatable: bool,
},
}
impl HirStatement {
pub fn from_ast_statement(ast_stmt: &decy_parser::parser::Statement) -> Self {
use decy_parser::parser::Statement;
match ast_stmt {
Statement::VariableDeclaration { name, var_type, initializer } => {
HirStatement::VariableDeclaration {
name: name.clone(),
var_type: HirType::from_ast_type(var_type),
initializer: initializer.as_ref().map(HirExpression::from_ast_expression),
}
}
Statement::Return(expr) => {
HirStatement::Return(expr.as_ref().map(HirExpression::from_ast_expression))
}
Statement::Assignment { target, value } => HirStatement::Assignment {
target: target.clone(),
value: HirExpression::from_ast_expression(value),
},
Statement::If { condition, then_block, else_block } => HirStatement::If {
condition: HirExpression::from_ast_expression(condition),
then_block: then_block.iter().map(HirStatement::from_ast_statement).collect(),
else_block: else_block
.as_ref()
.map(|block| block.iter().map(HirStatement::from_ast_statement).collect()),
},
Statement::For { init, condition, increment, body } => HirStatement::For {
init: init.iter().map(HirStatement::from_ast_statement).collect(),
condition: condition.as_ref().map(HirExpression::from_ast_expression),
increment: increment.iter().map(HirStatement::from_ast_statement).collect(),
body: body.iter().map(HirStatement::from_ast_statement).collect(),
},
Statement::While { condition, body } => HirStatement::While {
condition: HirExpression::from_ast_expression(condition),
body: body.iter().map(HirStatement::from_ast_statement).collect(),
},
Statement::DerefAssignment { target, value } => HirStatement::DerefAssignment {
target: HirExpression::from_ast_expression(target),
value: HirExpression::from_ast_expression(value),
},
Statement::ArrayIndexAssignment { array, index, value } => {
HirStatement::ArrayIndexAssignment {
array: Box::new(HirExpression::from_ast_expression(array)),
index: Box::new(HirExpression::from_ast_expression(index)),
value: HirExpression::from_ast_expression(value),
}
}
Statement::FieldAssignment { object, field, value } => HirStatement::FieldAssignment {
object: HirExpression::from_ast_expression(object),
field: field.clone(),
value: HirExpression::from_ast_expression(value),
},
Statement::Break => HirStatement::Break,
Statement::Continue => HirStatement::Continue,
Statement::PostIncrement { target } | Statement::PreIncrement { target } => {
HirStatement::Assignment {
target: target.clone(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Add,
left: Box::new(HirExpression::Variable(target.clone())),
right: Box::new(HirExpression::IntLiteral(1)),
},
}
}
Statement::PostDecrement { target } | Statement::PreDecrement { target } => {
HirStatement::Assignment {
target: target.clone(),
value: HirExpression::BinaryOp {
op: BinaryOperator::Subtract,
left: Box::new(HirExpression::Variable(target.clone())),
right: Box::new(HirExpression::IntLiteral(1)),
},
}
}
Statement::CompoundAssignment { target, op, value } => HirStatement::Assignment {
target: target.clone(),
value: HirExpression::BinaryOp {
op: convert_binary_operator(*op),
left: Box::new(HirExpression::Variable(target.clone())),
right: Box::new(HirExpression::from_ast_expression(value)),
},
},
Statement::DerefCompoundAssignment { target, op, value } => {
let hir_target = HirExpression::from_ast_expression(target);
HirStatement::DerefAssignment {
target: hir_target.clone(),
value: HirExpression::BinaryOp {
op: convert_binary_operator(*op),
left: Box::new(hir_target),
right: Box::new(HirExpression::from_ast_expression(value)),
},
}
}
Statement::Switch { condition, cases, default_case } => HirStatement::Switch {
condition: HirExpression::from_ast_expression(condition),
cases: cases
.iter()
.map(|case| SwitchCase {
value: case.value.as_ref().map(HirExpression::from_ast_expression),
body: case.body.iter().map(HirStatement::from_ast_statement).collect(),
})
.collect(),
default_case: default_case
.as_ref()
.map(|block| block.iter().map(HirStatement::from_ast_statement).collect()),
},
Statement::FunctionCall { function, arguments } => {
HirStatement::Expression(HirExpression::FunctionCall {
function: function.clone(),
arguments: arguments.iter().map(HirExpression::from_ast_expression).collect(),
})
}
}
}
}
impl HirExpression {
pub fn from_ast_expression(ast_expr: &decy_parser::parser::Expression) -> Self {
use decy_parser::parser::Expression;
match ast_expr {
Expression::IntLiteral(value) => HirExpression::IntLiteral(*value),
Expression::FloatLiteral(value) => HirExpression::FloatLiteral(value.clone()),
Expression::StringLiteral(value) => HirExpression::StringLiteral(value.clone()),
Expression::CharLiteral(value) => HirExpression::CharLiteral(*value),
Expression::Variable(name) => HirExpression::Variable(name.clone()),
Expression::BinaryOp { op, left, right } => HirExpression::BinaryOp {
op: convert_binary_operator(*op),
left: Box::new(HirExpression::from_ast_expression(left)),
right: Box::new(HirExpression::from_ast_expression(right)),
},
Expression::FunctionCall { function, arguments } => HirExpression::FunctionCall {
function: function.clone(),
arguments: arguments.iter().map(HirExpression::from_ast_expression).collect(),
},
Expression::Dereference(inner) => {
HirExpression::Dereference(Box::new(HirExpression::from_ast_expression(inner)))
}
Expression::UnaryOp { op, operand } => HirExpression::UnaryOp {
op: convert_unary_operator(*op),
operand: Box::new(HirExpression::from_ast_expression(operand)),
},
Expression::ArrayIndex { array, index } => HirExpression::ArrayIndex {
array: Box::new(HirExpression::from_ast_expression(array)),
index: Box::new(HirExpression::from_ast_expression(index)),
},
Expression::FieldAccess { object, field } => HirExpression::FieldAccess {
object: Box::new(HirExpression::from_ast_expression(object)),
field: field.clone(),
},
Expression::PointerFieldAccess { pointer, field } => {
HirExpression::PointerFieldAccess {
pointer: Box::new(HirExpression::from_ast_expression(pointer)),
field: field.clone(),
}
}
Expression::PostIncrement { operand } => HirExpression::PostIncrement {
operand: Box::new(HirExpression::from_ast_expression(operand)),
},
Expression::PreIncrement { operand } => HirExpression::PreIncrement {
operand: Box::new(HirExpression::from_ast_expression(operand)),
},
Expression::PostDecrement { operand } => HirExpression::PostDecrement {
operand: Box::new(HirExpression::from_ast_expression(operand)),
},
Expression::PreDecrement { operand } => HirExpression::PreDecrement {
operand: Box::new(HirExpression::from_ast_expression(operand)),
},
Expression::Sizeof { type_name } => {
HirExpression::Sizeof { type_name: type_name.clone() }
}
Expression::Cast { target_type, expr } => HirExpression::Cast {
target_type: HirType::from_ast_type(target_type),
expr: Box::new(HirExpression::from_ast_expression(expr)),
},
Expression::CompoundLiteral { literal_type, initializers } => {
HirExpression::CompoundLiteral {
literal_type: HirType::from_ast_type(literal_type),
initializers: initializers
.iter()
.map(HirExpression::from_ast_expression)
.collect(),
}
}
Expression::Ternary { condition, then_expr, else_expr } => HirExpression::Ternary {
condition: Box::new(HirExpression::from_ast_expression(condition)),
then_expr: Box::new(HirExpression::from_ast_expression(then_expr)),
else_expr: Box::new(HirExpression::from_ast_expression(else_expr)),
},
Expression::CxxNew { type_name, arguments } => HirExpression::CxxNew {
allocated_type: HirType::Struct(type_name.clone()),
arguments: arguments.iter().map(HirExpression::from_ast_expression).collect(),
},
Expression::CxxDelete { operand } => HirExpression::CxxDelete {
operand: Box::new(HirExpression::from_ast_expression(operand)),
},
Expression::NullLiteral => HirExpression::NullLiteral,
Expression::BoolLiteral(val) => {
if *val { HirExpression::IntLiteral(1) } else { HirExpression::IntLiteral(0) }
}
}
}
}
fn convert_unary_operator(op: decy_parser::parser::UnaryOperator) -> UnaryOperator {
use decy_parser::parser::UnaryOperator as ParserOp;
match op {
ParserOp::Minus => UnaryOperator::Minus,
ParserOp::LogicalNot => UnaryOperator::LogicalNot,
ParserOp::BitwiseNot => UnaryOperator::BitwiseNot,
ParserOp::AddressOf => UnaryOperator::AddressOf,
}
}
fn convert_binary_operator(op: decy_parser::parser::BinaryOperator) -> BinaryOperator {
use decy_parser::parser::BinaryOperator as ParserOp;
match op {
ParserOp::Add => BinaryOperator::Add,
ParserOp::Subtract => BinaryOperator::Subtract,
ParserOp::Multiply => BinaryOperator::Multiply,
ParserOp::Divide => BinaryOperator::Divide,
ParserOp::Modulo => BinaryOperator::Modulo,
ParserOp::Equal => BinaryOperator::Equal,
ParserOp::NotEqual => BinaryOperator::NotEqual,
ParserOp::LessThan => BinaryOperator::LessThan,
ParserOp::GreaterThan => BinaryOperator::GreaterThan,
ParserOp::LessEqual => BinaryOperator::LessEqual,
ParserOp::GreaterEqual => BinaryOperator::GreaterEqual,
ParserOp::LogicalAnd => BinaryOperator::LogicalAnd,
ParserOp::LogicalOr => BinaryOperator::LogicalOr,
ParserOp::LeftShift => BinaryOperator::LeftShift,
ParserOp::RightShift => BinaryOperator::RightShift,
ParserOp::BitwiseAnd => BinaryOperator::BitwiseAnd,
ParserOp::BitwiseOr => BinaryOperator::BitwiseOr,
ParserOp::BitwiseXor => BinaryOperator::BitwiseXor,
ParserOp::Assign => BinaryOperator::Assign,
ParserOp::Comma => BinaryOperator::Comma,
}
}
#[cfg(test)]
#[path = "hir_tests.rs"]
mod hir_tests;
#[cfg(test)]
#[path = "property_tests.rs"]
mod property_tests;
#[cfg(test)]
#[path = "statement_tests.rs"]
mod statement_tests;
#[cfg(test)]
#[path = "struct_tests.rs"]
mod struct_tests;
#[cfg(test)]
#[path = "array_indexing_tests.rs"]
mod array_indexing_tests;
#[cfg(test)]
#[path = "slice_index_tests.rs"]
mod slice_index_tests;
#[cfg(test)]
#[path = "for_loop_tests.rs"]
mod for_loop_tests;
#[cfg(test)]
#[path = "typedef_tests.rs"]
mod typedef_tests;
#[cfg(test)]
#[path = "typedef_property_tests.rs"]
mod typedef_property_tests;
#[cfg(test)]
#[path = "function_pointer_tests.rs"]
mod function_pointer_tests;
#[cfg(test)]
#[path = "string_tests.rs"]
mod string_tests;
#[cfg(test)]
#[path = "string_property_tests.rs"]
mod string_property_tests;
#[cfg(test)]
#[path = "switch_tests.rs"]
mod switch_tests;
#[cfg(test)]
#[path = "macro_definition_tests.rs"]
mod macro_definition_tests;
#[cfg(test)]
#[path = "coverage_tests.rs"]
mod coverage_tests;