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;
|
||||
|
||||
impl Transpilable for Binding {
|
||||
/// Transpiles val and var bindings into JS.
|
||||
/// Transpiles val and var bindings into PHP.
|
||||
fn transpile(&self) -> String {
|
||||
match self {
|
||||
Binding::Val(val_binding) => {
|
||||
let expression_str = val_binding.expression.transpile();
|
||||
|
||||
format!("const {} = {};", val_binding.identifier, expression_str)
|
||||
format!("${} = {};", val_binding.identifier, expression_str)
|
||||
}
|
||||
Binding::Var(var_binding) => {
|
||||
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();
|
||||
|
||||
assert_eq!("const identifier = 322;", result);
|
||||
assert_eq!("$identifier = 322;", result);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use super::Transpilable;
|
||||
use crate::syntax::ast::Expression;
|
||||
|
||||
impl Transpilable for Expression {
|
||||
/// Transpiles an Expression to JS
|
||||
/// Transpiles an Expression to PHP
|
||||
///
|
||||
/// Right now the expressions in the grammar are:
|
||||
/// - Number
|
||||
|
@ -4,13 +4,13 @@ mod binding;
|
||||
mod expression;
|
||||
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 {
|
||||
/// Transforms this struct into JavaScript
|
||||
/// Transforms this struct into PHP
|
||||
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 {
|
||||
ast.transpile()
|
||||
}
|
||||
@ -29,6 +29,6 @@ mod tests {
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
fn transpile(&self) -> String {
|
||||
let bindings_str: Vec<String> = self
|
||||
@ -36,6 +36,6 @@ mod tests {
|
||||
|
||||
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::{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);
|
||||
|
||||
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 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);
|
||||
fs::write(output_path, js_code).expect("Error writing to output path");
|
||||
let mut output_path = Path::new(input).canonicalize().unwrap();
|
||||
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
|
||||
|
@ -27,9 +27,6 @@ enum Commands {
|
||||
C {
|
||||
/// File to compile
|
||||
file: String,
|
||||
|
||||
/// File to write the JS code to
|
||||
output: String,
|
||||
},
|
||||
/// Starts the REPL
|
||||
R {},
|
||||
@ -49,15 +46,14 @@ fn get_copyright() -> String {
|
||||
/// Usage:
|
||||
/// - `misti` : 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() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match &cli.command {
|
||||
Some(Commands::C {
|
||||
file: input,
|
||||
output,
|
||||
}) => file::compile_file(input, output),
|
||||
}) => file::compile_file(input),
|
||||
Some(Commands::R {}) => {
|
||||
println!("{}", get_copyright());
|
||||
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<()> {
|
||||
let stdin = io::stdin();
|
||||
let mut buffer = String::new();
|
||||
|
Loading…
Reference in New Issue
Block a user