Compare commits
No commits in common. "6eef841e84cb4a4447497ae5d3ed59c4caa55fb8" and "4c565df69924cc2d3d2f5579dde3ae585d010ba4" have entirely different histories.
6eef841e84
...
4c565df699
@ -25,11 +25,6 @@
|
|||||||
- Begin work on the code formatter
|
- Begin work on the code formatter
|
||||||
|
|
||||||
|
|
||||||
## v0.1.1
|
|
||||||
|
|
||||||
- [x] Top level expressions as statements
|
|
||||||
- [ ] Naively transpile variable bindings
|
|
||||||
|
|
||||||
## v0.1.0
|
## v0.1.0
|
||||||
|
|
||||||
- [x] Complete workflow for "Hello world"
|
- [x] Complete workflow for "Hello world"
|
||||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -92,7 +92,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thp"
|
name = "thp"
|
||||||
version = "0.1.0"
|
version = "0.0.14"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colored",
|
"colored",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "thp"
|
name = "thp"
|
||||||
version = "0.1.0"
|
version = "0.0.14"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
use crate::{codegen::Transpilable, php_ast::PhpAssignmentExpression};
|
|
||||||
|
|
||||||
impl Transpilable for PhpAssignmentExpression<'_> {
|
|
||||||
fn transpile(&self) -> String {
|
|
||||||
match self {
|
|
||||||
PhpAssignmentExpression::Primary(p) => p.transpile(),
|
|
||||||
PhpAssignmentExpression::SimpleAssignment(assignment) => {
|
|
||||||
let variable_name = &assignment.variable;
|
|
||||||
let expression_str = assignment.assignment.transpile();
|
|
||||||
|
|
||||||
format!("${} = {}", variable_name, expression_str)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{
|
|
||||||
codegen::Transpilable,
|
|
||||||
php_ast::{PhpAssignmentExpression, PhpPrimaryExpression, PhpSimpleAssignment},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_gen_assignment() {
|
|
||||||
let variable = String::from("name");
|
|
||||||
let value = String::from("John");
|
|
||||||
let assignment = PhpPrimaryExpression::StringLiteral(&value);
|
|
||||||
|
|
||||||
let ast = PhpAssignmentExpression::SimpleAssignment(PhpSimpleAssignment {
|
|
||||||
variable,
|
|
||||||
assignment,
|
|
||||||
});
|
|
||||||
let output = ast.transpile();
|
|
||||||
|
|
||||||
assert_eq!("$name = \"John\"", output)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +1 @@
|
|||||||
mod assignment;
|
|
||||||
mod primary_expression;
|
mod primary_expression;
|
||||||
|
@ -6,7 +6,6 @@ impl Transpilable for PhpPrimaryExpression<'_> {
|
|||||||
PhpPrimaryExpression::IntegerLiteral(value) => value.to_string(),
|
PhpPrimaryExpression::IntegerLiteral(value) => value.to_string(),
|
||||||
PhpPrimaryExpression::FloatingLiteral(value) => value.to_string(),
|
PhpPrimaryExpression::FloatingLiteral(value) => value.to_string(),
|
||||||
PhpPrimaryExpression::StringLiteral(value) => format!("\"{}\"", value),
|
PhpPrimaryExpression::StringLiteral(value) => format!("\"{}\"", value),
|
||||||
PhpPrimaryExpression::Variable(name) => format!("${}", name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,13 +58,4 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!("322.644", output)
|
assert_eq!("322.644", output)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transpile_variable() {
|
|
||||||
let input = String::from("name");
|
|
||||||
let ast = PhpPrimaryExpression::Variable(&input);
|
|
||||||
let output = ast.transpile();
|
|
||||||
|
|
||||||
assert_eq!("$name", output)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ pub mod statement_list;
|
|||||||
impl Transpilable for PhpExpression<'_> {
|
impl Transpilable for PhpExpression<'_> {
|
||||||
fn transpile(&self) -> String {
|
fn transpile(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
PhpExpression::Assignment(p) => p.transpile(),
|
PhpExpression::PrimaryExpression(p) => p.transpile(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,6 @@ impl Transpilable for PhpStatement<'_> {
|
|||||||
|
|
||||||
format!("echo {};", expressions_str)
|
format!("echo {};", expressions_str)
|
||||||
}
|
}
|
||||||
PhpStatement::PhpExpressionStatement(expr) => {
|
|
||||||
let expr_str = expr.transpile();
|
|
||||||
format!("{};", expr_str)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,10 +28,7 @@ impl Transpilable for PhpStatement<'_> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::Transpilable,
|
codegen::Transpilable,
|
||||||
php_ast::{
|
php_ast::{PhpExpression, PhpExpressionList, PhpPrimaryExpression, PhpStatement},
|
||||||
PhpAssignmentExpression, PhpExpression, PhpExpressionList, PhpPrimaryExpression,
|
|
||||||
PhpStatement,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -54,9 +47,7 @@ mod tests {
|
|||||||
let input = String::from("322");
|
let input = String::from("322");
|
||||||
let exp_1 = PhpPrimaryExpression::FloatingLiteral(&input);
|
let exp_1 = PhpPrimaryExpression::FloatingLiteral(&input);
|
||||||
let expressions = PhpExpressionList {
|
let expressions = PhpExpressionList {
|
||||||
expressions: vec![PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
expressions: vec![PhpExpression::PrimaryExpression(exp_1)],
|
||||||
exp_1,
|
|
||||||
))],
|
|
||||||
};
|
};
|
||||||
let ast = PhpStatement::PhpEchoStatement(expressions);
|
let ast = PhpStatement::PhpEchoStatement(expressions);
|
||||||
let output = ast.transpile();
|
let output = ast.transpile();
|
||||||
@ -74,8 +65,8 @@ mod tests {
|
|||||||
|
|
||||||
let expressions = PhpExpressionList {
|
let expressions = PhpExpressionList {
|
||||||
expressions: vec![
|
expressions: vec![
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(exp_1)),
|
PhpExpression::PrimaryExpression(exp_1),
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(exp_2)),
|
PhpExpression::PrimaryExpression(exp_2),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
let ast = PhpStatement::PhpEchoStatement(expressions);
|
let ast = PhpStatement::PhpEchoStatement(expressions);
|
||||||
@ -83,16 +74,4 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!("echo 322, \"Hai world\";", output)
|
assert_eq!("echo 322, \"Hai world\";", output)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_gen_expression_stmt() {
|
|
||||||
let input = String::from("Hi!");
|
|
||||||
let exp_1 = PhpPrimaryExpression::StringLiteral(&input);
|
|
||||||
let ast = PhpStatement::PhpExpressionStatement(PhpExpression::Assignment(
|
|
||||||
PhpAssignmentExpression::Primary(exp_1),
|
|
||||||
));
|
|
||||||
let output = ast.transpile();
|
|
||||||
|
|
||||||
assert_eq!("\"Hi!\";", output)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,7 @@ impl Transpilable for PhpAst<'_> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{codegen::Transpilable, php_ast::PhpAst};
|
||||||
codegen::Transpilable,
|
|
||||||
php_ast::{
|
|
||||||
PhpAssignmentExpression, PhpAst, PhpExpression, PhpPrimaryExpression, PhpStatement,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_transpile_empty_file() {
|
fn should_transpile_empty_file() {
|
||||||
@ -28,19 +23,4 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!("<?php\n", output);
|
assert_eq!("<?php\n", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transpile_expr_statement() {
|
|
||||||
let value = String::from("Hello world!");
|
|
||||||
let ast = PhpAst {
|
|
||||||
statements: vec![PhpStatement::PhpExpressionStatement(
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::StringLiteral(&value),
|
|
||||||
)),
|
|
||||||
)],
|
|
||||||
};
|
|
||||||
let output = ast.transpile();
|
|
||||||
|
|
||||||
assert_eq!("<?php\n\"Hello world!\";", output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ pub struct PhpAst<'a> {
|
|||||||
/// echo-statement
|
/// echo-statement
|
||||||
pub enum PhpStatement<'a> {
|
pub enum PhpStatement<'a> {
|
||||||
PhpEchoStatement(PhpExpressionList<'a>),
|
PhpEchoStatement(PhpExpressionList<'a>),
|
||||||
PhpExpressionStatement(PhpExpression<'a>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PhpExpressionList<'a> {
|
pub struct PhpExpressionList<'a> {
|
||||||
@ -27,30 +26,15 @@ pub struct PhpExpressionList<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum PhpExpression<'a> {
|
pub enum PhpExpression<'a> {
|
||||||
Assignment(PhpAssignmentExpression<'a>),
|
PrimaryExpression(PhpPrimaryExpression<'a>),
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PhpAssignmentExpression<'a> {
|
|
||||||
Primary(PhpPrimaryExpression<'a>),
|
|
||||||
SimpleAssignment(PhpSimpleAssignment<'a>),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PhpSimpleAssignment<'a> {
|
|
||||||
pub variable: String,
|
|
||||||
pub assignment: PhpPrimaryExpression<'a>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://phplang.org/spec/19-grammar.html#grammar-primary-expression
|
/// https://phplang.org/spec/19-grammar.html#grammar-primary-expression
|
||||||
///
|
///
|
||||||
/// primary-expression:
|
/// primary-expression:
|
||||||
/// literal
|
/// literal
|
||||||
/// variable
|
|
||||||
pub enum PhpPrimaryExpression<'a> {
|
pub enum PhpPrimaryExpression<'a> {
|
||||||
IntegerLiteral(&'a String),
|
IntegerLiteral(&'a String),
|
||||||
FloatingLiteral(&'a String),
|
FloatingLiteral(&'a String),
|
||||||
StringLiteral(&'a String),
|
StringLiteral(&'a String),
|
||||||
/// https://phplang.org/spec/19-grammar.html#grammar-variable
|
|
||||||
///
|
|
||||||
/// Supports only variable -> callable-variable -> simple-variable -> variable-name
|
|
||||||
Variable(&'a String),
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
use super::super::PhpExpression;
|
use super::super::PhpExpression;
|
||||||
use crate::{
|
use crate::{php_ast::PhpPrimaryExpression, syntax::ast::Expression};
|
||||||
php_ast::{PhpAssignmentExpression, PhpPrimaryExpression},
|
|
||||||
syntax::ast::Expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::PHPTransformable;
|
use super::PHPTransformable;
|
||||||
|
|
||||||
@ -14,76 +11,9 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
|||||||
match self {
|
match self {
|
||||||
Expression::String(value) => {
|
Expression::String(value) => {
|
||||||
let expr = PhpPrimaryExpression::StringLiteral(value);
|
let expr = PhpPrimaryExpression::StringLiteral(value);
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(expr))
|
PhpExpression::PrimaryExpression(expr)
|
||||||
}
|
|
||||||
Expression::Int(value) => {
|
|
||||||
let expr = PhpPrimaryExpression::IntegerLiteral(value);
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(expr))
|
|
||||||
}
|
|
||||||
Expression::Float(value) => {
|
|
||||||
let expr = PhpPrimaryExpression::FloatingLiteral(value);
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(expr))
|
|
||||||
}
|
}
|
||||||
_ => todo!("transformation for expression: {:?}", self),
|
_ => todo!("transformation for expression: {:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{
|
|
||||||
php_ast::{
|
|
||||||
transformers::PHPTransformable, PhpAssignmentExpression, PhpExpression,
|
|
||||||
PhpPrimaryExpression,
|
|
||||||
},
|
|
||||||
syntax::ast::Expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transform_string() {
|
|
||||||
let value = String::from("Hello");
|
|
||||||
let input = Expression::String(&value);
|
|
||||||
let output = input.into_php_ast();
|
|
||||||
|
|
||||||
match output {
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::StringLiteral(value),
|
|
||||||
)) => {
|
|
||||||
assert_eq!("Hello", value)
|
|
||||||
}
|
|
||||||
_ => panic!("Expected a String literal"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transform_int() {
|
|
||||||
let value = String::from("322");
|
|
||||||
let input = Expression::Int(&value);
|
|
||||||
let output = input.into_php_ast();
|
|
||||||
|
|
||||||
match output {
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::IntegerLiteral(value),
|
|
||||||
)) => {
|
|
||||||
assert_eq!("322", value)
|
|
||||||
}
|
|
||||||
_ => panic!("Expected a Int literal"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transform_float() {
|
|
||||||
let value = String::from("322.644");
|
|
||||||
let input = Expression::Float(&value);
|
|
||||||
let output = input.into_php_ast();
|
|
||||||
|
|
||||||
match output {
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::FloatingLiteral(value),
|
|
||||||
)) => {
|
|
||||||
assert_eq!("322.644", value)
|
|
||||||
}
|
|
||||||
_ => panic!("Expected a Float literal"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use super::super::PhpAst;
|
use super::super::PhpAst;
|
||||||
use crate::php_ast::{
|
use crate::php_ast::{PhpExpression, PhpExpressionList, PhpPrimaryExpression, PhpStatement};
|
||||||
PhpAssignmentExpression, PhpExpression, PhpExpressionList, PhpPrimaryExpression, PhpStatement,
|
|
||||||
};
|
|
||||||
use crate::syntax::ast::{Expression, ModuleAST, ModuleMembers};
|
use crate::syntax::ast::{Expression, ModuleAST, ModuleMembers};
|
||||||
|
|
||||||
use super::PHPTransformable;
|
use super::PHPTransformable;
|
||||||
@ -22,7 +20,6 @@ impl<'a> PHPTransformable<'a> for ModuleAST<'_> {
|
|||||||
// TODO: This should be done by the Expression transformer
|
// TODO: This should be done by the Expression transformer
|
||||||
match expr {
|
match expr {
|
||||||
Expression::FunctionCall(fc) => {
|
Expression::FunctionCall(fc) => {
|
||||||
// TODO: This definitely needs refactoring
|
|
||||||
let function_expr: &Expression = &*fc.function;
|
let function_expr: &Expression = &*fc.function;
|
||||||
match function_expr {
|
match function_expr {
|
||||||
Expression::Identifier(id) if *id == "print" => {
|
Expression::Identifier(id) if *id == "print" => {
|
||||||
@ -37,7 +34,7 @@ impl<'a> PHPTransformable<'a> for ModuleAST<'_> {
|
|||||||
match e {
|
match e {
|
||||||
Expression::String(v) => {
|
Expression::String(v) => {
|
||||||
expressions.push(
|
expressions.push(
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(PhpPrimaryExpression::StringLiteral(v)))
|
PhpExpression::PrimaryExpression(PhpPrimaryExpression::StringLiteral(v))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
_ => todo!("Non string expressions not supported")
|
_ => todo!("Non string expressions not supported")
|
||||||
@ -51,27 +48,6 @@ impl<'a> PHPTransformable<'a> for ModuleAST<'_> {
|
|||||||
_ => todo!("Not implemented: AST transformation for function call that is not an identifier")
|
_ => todo!("Not implemented: AST transformation for function call that is not an identifier")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Int(value) => {
|
|
||||||
php_statements.push(PhpStatement::PhpExpressionStatement(
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::IntegerLiteral(value),
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Expression::Float(value) => {
|
|
||||||
php_statements.push(PhpStatement::PhpExpressionStatement(
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::FloatingLiteral(value),
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Expression::String(value) => {
|
|
||||||
php_statements.push(PhpStatement::PhpExpressionStatement(
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(
|
|
||||||
PhpPrimaryExpression::StringLiteral(value),
|
|
||||||
)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
todo!("not implemented: AST transform for expression {:?}", expr)
|
todo!("not implemented: AST transform for expression {:?}", expr)
|
||||||
}
|
}
|
||||||
@ -85,18 +61,3 @@ impl<'a> PHPTransformable<'a> for ModuleAST<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{php_ast::transformers::PHPTransformable, syntax::ast::ModuleAST};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transform_empty_ast() {
|
|
||||||
let input = ModuleAST {
|
|
||||||
productions: vec![],
|
|
||||||
};
|
|
||||||
let output = input.into_php_ast();
|
|
||||||
|
|
||||||
assert!(output.statements.is_empty())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
use super::super::PhpStatement;
|
use super::super::PhpStatement;
|
||||||
use crate::{
|
use crate::syntax::ast::Statement;
|
||||||
php_ast::{PhpAssignmentExpression, PhpExpression, PhpSimpleAssignment},
|
|
||||||
syntax::ast::Statement,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::PHPTransformable;
|
use super::PHPTransformable;
|
||||||
|
|
||||||
@ -12,76 +9,7 @@ impl<'a> PHPTransformable<'a> for Statement<'_> {
|
|||||||
|
|
||||||
fn into_php_ast(&'a self) -> Self::Item {
|
fn into_php_ast(&'a self) -> Self::Item {
|
||||||
match self {
|
match self {
|
||||||
Statement::Binding(b) => {
|
|
||||||
// This is a PhpExpression, but a PhpPrimaryExpression is needed
|
|
||||||
let binding_expr = b.expression.into_php_ast();
|
|
||||||
|
|
||||||
// TODO: Somehow fix this...
|
|
||||||
// the function above `into_php_ast` should somehow
|
|
||||||
// return what I need? Or should return something general and
|
|
||||||
// then i decide how to transform it here?
|
|
||||||
// if it reaches this point in the pipeline, is it
|
|
||||||
// safe to assume that any AST is correct, since
|
|
||||||
// semantic analysis (supposedly) did its job?
|
|
||||||
let binding_primary_expr = match binding_expr {
|
|
||||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(p)) => p,
|
|
||||||
_ => unreachable!("Expected a PrimaryExpression during AST transformation"),
|
|
||||||
};
|
|
||||||
|
|
||||||
PhpStatement::PhpExpressionStatement(PhpExpression::Assignment(
|
|
||||||
PhpAssignmentExpression::SimpleAssignment(PhpSimpleAssignment {
|
|
||||||
variable: b.identifier.value.clone(),
|
|
||||||
assignment: binding_primary_expr,
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
_ => todo!("transformation for statement: {:?}", self),
|
_ => todo!("transformation for statement: {:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{
|
|
||||||
lexic::token::{Token, TokenType},
|
|
||||||
php_ast::{
|
|
||||||
transformers::PHPTransformable, PhpAssignmentExpression, PhpExpression,
|
|
||||||
PhpPrimaryExpression, PhpStatement,
|
|
||||||
},
|
|
||||||
syntax::ast::{var_binding::VariableBinding, Expression, Statement},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_transform_binding() {
|
|
||||||
let identifier_token = Token {
|
|
||||||
token_type: TokenType::Identifier,
|
|
||||||
value: "name".into(),
|
|
||||||
position: 0,
|
|
||||||
};
|
|
||||||
let expr_value = String::from("Hello");
|
|
||||||
let expression = Expression::String(&expr_value);
|
|
||||||
let binding = Statement::Binding(VariableBinding {
|
|
||||||
datatype: None,
|
|
||||||
identifier: &identifier_token,
|
|
||||||
expression,
|
|
||||||
is_mutable: false,
|
|
||||||
});
|
|
||||||
let output = binding.into_php_ast();
|
|
||||||
|
|
||||||
match output {
|
|
||||||
PhpStatement::PhpExpressionStatement(PhpExpression::Assignment(
|
|
||||||
PhpAssignmentExpression::SimpleAssignment(assignment),
|
|
||||||
)) => {
|
|
||||||
assert_eq!("name", assignment.variable);
|
|
||||||
|
|
||||||
match assignment.assignment {
|
|
||||||
PhpPrimaryExpression::StringLiteral(value) => {
|
|
||||||
assert_eq!("Hello", value);
|
|
||||||
}
|
|
||||||
_ => panic!("Expected a String literal as the value of the assignment"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("Expected an ExpressionStatement"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -33,6 +33,22 @@ impl SemanticCheck for Statement<'_> {
|
|||||||
// TODO: Move to its own file when it grows
|
// TODO: Move to its own file when it grows
|
||||||
impl SemanticCheck for Expression<'_> {
|
impl SemanticCheck for Expression<'_> {
|
||||||
fn check_semantics(&self, scope: &SymbolTable) -> Result<(), MistiError> {
|
fn check_semantics(&self, scope: &SymbolTable) -> Result<(), MistiError> {
|
||||||
|
// How to get the global definition into the symbol table?
|
||||||
|
// maybe just when creating the symbol table inject all
|
||||||
|
// the global elements at once?
|
||||||
|
// Store the global elements as binary/JSON
|
||||||
|
// and load them along with the symbol table
|
||||||
|
|
||||||
|
// then for efficiency they could be grouped by module?
|
||||||
|
// and stored as binary files?
|
||||||
|
// then the binary files are searched for and loaded when
|
||||||
|
// requested?
|
||||||
|
|
||||||
|
// For a function call:
|
||||||
|
// check that the function exists
|
||||||
|
// check its signature
|
||||||
|
// check parameters
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Expression::FunctionCall(f) => {
|
Expression::FunctionCall(f) => {
|
||||||
let fun = &*f.function;
|
let fun = &*f.function;
|
||||||
@ -88,11 +104,7 @@ impl SemanticCheck for Expression<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::Int(_) => {}
|
_ => todo!("Check semantics for expression other than function call"),
|
||||||
Expression::Float(_) => {}
|
|
||||||
Expression::String(_) => {}
|
|
||||||
Expression::Boolean(_) => {}
|
|
||||||
_ => todo!("Check semantics for expression other than function call and primitive"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -62,6 +62,8 @@ pub struct Parameter<'a> {
|
|||||||
pub enum Expression<'a> {
|
pub enum Expression<'a> {
|
||||||
Int(&'a String),
|
Int(&'a String),
|
||||||
Float(&'a String),
|
Float(&'a String),
|
||||||
|
// TODO: Specify if this contains or not the original quotes ""
|
||||||
|
// TODO: After this fix where neccesary
|
||||||
String(&'a String),
|
String(&'a String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Identifier(&'a String),
|
Identifier(&'a String),
|
||||||
|
Loading…
Reference in New Issue
Block a user