Changes to codegen to move from JS to PHP generation
This commit is contained in:
parent
94f0b0c92d
commit
c61f88aaaa
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# THP: Typed Hypertext Processor
|
||||||
|
|
||||||
|
Types and a new syntax for PHP, because I'm forced to use it at work.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Singular files
|
||||||
|
|
||||||
|
Inside an existing PHP codebase, files are converted to THP
|
||||||
|
one at a time, or new files are written in THP.
|
||||||
|
|
||||||
|
There must be a thp.config.yaml at the root of the project,
|
||||||
|
which configures the compiler.
|
||||||
|
|
||||||
|
Every file is compiled in place.
|
||||||
|
|
||||||
|
|
||||||
|
### Project mode
|
||||||
|
|
||||||
|
The whole project uses THP. Work in progress.
|
||||||
|
|
||||||
|
|
@ -2,18 +2,18 @@ use super::Transpilable;
|
|||||||
use crate::syntax::ast::Binding;
|
use crate::syntax::ast::Binding;
|
||||||
|
|
||||||
impl Transpilable for Binding {
|
impl Transpilable for Binding {
|
||||||
/// Transpiles val and var bindings into JS.
|
/// Transpiles val and var bindings into PHP.
|
||||||
fn transpile(&self) -> String {
|
fn transpile(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Binding::Val(val_binding) => {
|
Binding::Val(val_binding) => {
|
||||||
let expression_str = val_binding.expression.transpile();
|
let expression_str = val_binding.expression.transpile();
|
||||||
|
|
||||||
format!("const {} = {};", val_binding.identifier, expression_str)
|
format!("${} = {};", val_binding.identifier, expression_str)
|
||||||
}
|
}
|
||||||
Binding::Var(var_binding) => {
|
Binding::Var(var_binding) => {
|
||||||
let expression_str = var_binding.expression.transpile();
|
let expression_str = var_binding.expression.transpile();
|
||||||
|
|
||||||
format!("let {} = {};", var_binding.identifier, expression_str)
|
format!("${} = {};", var_binding.identifier, expression_str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,6 +36,6 @@ mod tests {
|
|||||||
|
|
||||||
let result = binding.transpile();
|
let result = binding.transpile();
|
||||||
|
|
||||||
assert_eq!("const identifier = 322;", result);
|
assert_eq!("$identifier = 322;", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use super::Transpilable;
|
|||||||
use crate::syntax::ast::Expression;
|
use crate::syntax::ast::Expression;
|
||||||
|
|
||||||
impl Transpilable for Expression {
|
impl Transpilable for Expression {
|
||||||
/// Transpiles an Expression to JS
|
/// Transpiles an Expression to PHP
|
||||||
///
|
///
|
||||||
/// Right now the expressions in the grammar are:
|
/// Right now the expressions in the grammar are:
|
||||||
/// - Number
|
/// - Number
|
||||||
|
@ -4,13 +4,13 @@ mod binding;
|
|||||||
mod expression;
|
mod expression;
|
||||||
mod module_ast;
|
mod module_ast;
|
||||||
|
|
||||||
/// Trait that the AST and its nodes implement to support transformation to JavaScript
|
/// Trait that the AST and its nodes implement to support transformation to PHP
|
||||||
trait Transpilable {
|
trait Transpilable {
|
||||||
/// Transforms this struct into JavaScript
|
/// Transforms this struct into PHP
|
||||||
fn transpile(&self) -> String;
|
fn transpile(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms an AST to its representation in JavaScript
|
/// Transforms an AST to its representation in PHP
|
||||||
pub fn codegen<'a>(ast: &'a ModuleAST) -> String {
|
pub fn codegen<'a>(ast: &'a ModuleAST) -> String {
|
||||||
ast.transpile()
|
ast.transpile()
|
||||||
}
|
}
|
||||||
@ -29,6 +29,6 @@ mod tests {
|
|||||||
|
|
||||||
let out_str = codegen(&ast);
|
let out_str = codegen(&ast);
|
||||||
|
|
||||||
assert_eq!("const id = 322;", out_str);
|
assert_eq!("$id = 322;", out_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use super::Transpilable;
|
|||||||
use crate::syntax::ast::ModuleAST;
|
use crate::syntax::ast::ModuleAST;
|
||||||
|
|
||||||
impl Transpilable for ModuleAST {
|
impl Transpilable for ModuleAST {
|
||||||
/// Transpiles the whole AST into JS, using this same trait on the
|
/// Transpiles the whole AST into PHP, using this same trait on the
|
||||||
/// nodes and leaves of the AST
|
/// nodes and leaves of the AST
|
||||||
fn transpile(&self) -> String {
|
fn transpile(&self) -> String {
|
||||||
let bindings_str: Vec<String> = self
|
let bindings_str: Vec<String> = self
|
||||||
@ -36,6 +36,6 @@ mod tests {
|
|||||||
|
|
||||||
let result = module.transpile();
|
let result = module.transpile();
|
||||||
|
|
||||||
assert_eq!("const identifier = 322;", result);
|
assert_eq!("$identifier = 322;", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::{fs, path::Path};
|
|||||||
use crate::lexic::token::Token;
|
use crate::lexic::token::Token;
|
||||||
use crate::{codegen, error_handling::PrintableError, lexic, syntax};
|
use crate::{codegen, error_handling::PrintableError, lexic, syntax};
|
||||||
|
|
||||||
pub fn compile_file(input: &String, output: &String) {
|
pub fn compile_file(input: &String) {
|
||||||
let input_path = Path::new(input);
|
let input_path = Path::new(input);
|
||||||
|
|
||||||
if !input_path.is_file() {
|
if !input_path.is_file() {
|
||||||
@ -13,10 +13,11 @@ pub fn compile_file(input: &String, output: &String) {
|
|||||||
let bytes = fs::read(input_path).expect("INPUT_PATH should be valid");
|
let bytes = fs::read(input_path).expect("INPUT_PATH should be valid");
|
||||||
let contents = String::from_utf8(bytes).expect("INPUT_PATH's encoding MUST be UTF-8");
|
let contents = String::from_utf8(bytes).expect("INPUT_PATH's encoding MUST be UTF-8");
|
||||||
|
|
||||||
let js_code = compile(&contents);
|
let out_code = compile(&contents);
|
||||||
|
|
||||||
let output_path = Path::new(output);
|
let mut output_path = Path::new(input).canonicalize().unwrap();
|
||||||
fs::write(output_path, js_code).expect("Error writing to output path");
|
output_path.set_extension("php");
|
||||||
|
fs::write(output_path, out_code).expect("Error writing to output path");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase
|
||||||
|
@ -27,9 +27,6 @@ enum Commands {
|
|||||||
C {
|
C {
|
||||||
/// File to compile
|
/// File to compile
|
||||||
file: String,
|
file: String,
|
||||||
|
|
||||||
/// File to write the JS code to
|
|
||||||
output: String,
|
|
||||||
},
|
},
|
||||||
/// Starts the REPL
|
/// Starts the REPL
|
||||||
R {},
|
R {},
|
||||||
@ -49,15 +46,14 @@ fn get_copyright() -> String {
|
|||||||
/// Usage:
|
/// Usage:
|
||||||
/// - `misti` : Starts the compiler in watch mode
|
/// - `misti` : Starts the compiler in watch mode
|
||||||
/// - `misti w, --watch, -w` : Starts the compiler in watch mode
|
/// - `misti w, --watch, -w` : Starts the compiler in watch mode
|
||||||
/// - `misti -c FILE -o OUTPUT` : Compiles FILE and writes the result in OUTPUT
|
/// - `misti c FILE` : Compiles FILE and writes the result in the same directory
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
match &cli.command {
|
match &cli.command {
|
||||||
Some(Commands::C {
|
Some(Commands::C {
|
||||||
file: input,
|
file: input,
|
||||||
output,
|
}) => file::compile_file(input),
|
||||||
}) => file::compile_file(input, output),
|
|
||||||
Some(Commands::R {}) => {
|
Some(Commands::R {}) => {
|
||||||
println!("{}", get_copyright());
|
println!("{}", get_copyright());
|
||||||
let _ = repl::run();
|
let _ = repl::run();
|
||||||
|
@ -40,7 +40,7 @@ fn build_ast(input: &String, tokens: Vec<Token>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes the REPL, reading from stdin, compiling and emitting JS to stdout
|
/// Executes the REPL, reading from stdin, compiling and emitting PHP to stdout
|
||||||
pub fn run() -> io::Result<()> {
|
pub fn run() -> io::Result<()> {
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user