feat: Naive transpiling of variable bindings
This commit is contained in:
parent
9cd1b70103
commit
6eef841e84
@ -28,6 +28,7 @@
|
||||
## v0.1.1
|
||||
|
||||
- [x] Top level expressions as statements
|
||||
- [ ] Naively transpile variable bindings
|
||||
|
||||
## v0.1.0
|
||||
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -92,7 +92,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thp"
|
||||
version = "0.0.14"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"serde",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "thp"
|
||||
version = "0.0.14"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
mod primary_expression;
|
||||
mod assignment;
|
||||
mod primary_expression;
|
||||
|
@ -14,7 +14,12 @@ impl Transpilable for PhpAst<'_> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{codegen::Transpilable, php_ast::PhpAst};
|
||||
use crate::{
|
||||
codegen::Transpilable,
|
||||
php_ast::{
|
||||
PhpAssignmentExpression, PhpAst, PhpExpression, PhpPrimaryExpression, PhpStatement,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn should_transpile_empty_file() {
|
||||
@ -23,4 +28,19 @@ mod tests {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,74 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
||||
let expr = PhpPrimaryExpression::StringLiteral(value);
|
||||
PhpExpression::Assignment(PhpAssignmentExpression::Primary(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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,3 +85,18 @@ 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,5 +1,8 @@
|
||||
use super::super::PhpStatement;
|
||||
use crate::syntax::ast::Statement;
|
||||
use crate::{
|
||||
php_ast::{PhpAssignmentExpression, PhpExpression, PhpSimpleAssignment},
|
||||
syntax::ast::Statement,
|
||||
};
|
||||
|
||||
use super::PHPTransformable;
|
||||
|
||||
@ -9,7 +12,76 @@ impl<'a> PHPTransformable<'a> for Statement<'_> {
|
||||
|
||||
fn into_php_ast(&'a self) -> Self::Item {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,10 +88,10 @@ impl SemanticCheck for Expression<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Expression::Int(_) => {},
|
||||
Expression::Float(_) => {},
|
||||
Expression::String(_) => {},
|
||||
Expression::Boolean(_) => {},
|
||||
Expression::Int(_) => {}
|
||||
Expression::Float(_) => {}
|
||||
Expression::String(_) => {}
|
||||
Expression::Boolean(_) => {}
|
||||
_ => todo!("Check semantics for expression other than function call and primitive"),
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user