added main.tp entrypoint
This commit is contained in:
parent
215dc13797
commit
05279201c8
7 changed files with 33 additions and 36 deletions
|
|
@ -235,7 +235,3 @@ ISSUES
|
||||||
* improve indenting
|
* improve indenting
|
||||||
|
|
||||||
WIP guards
|
WIP guards
|
||||||
* | /$uuid -> service.get(uuid)?
|
|
||||||
| /&first_name -> service.get_by_firstname(first_name)?
|
|
||||||
| /&last_name -> service.get_by_lastname(last_name)?
|
|
||||||
| 404
|
|
||||||
|
|
@ -1,18 +1,7 @@
|
||||||
* currently needs postgres on the default port
|
* currently needs postgres on the default port
|
||||||
* user 'postgres'
|
* user 'postgres'
|
||||||
* password 'boompje'
|
* password 'boompje'
|
||||||
* create a table
|
|
||||||
```
|
|
||||||
create table customers(
|
|
||||||
id bigint primary key,
|
|
||||||
first_name varchar(50),
|
|
||||||
last_name varchar(50)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
* insert data
|
|
||||||
```
|
|
||||||
insert into customers (first_name,last_name) values ('first', 'last')
|
|
||||||
```
|
|
||||||
* run ```cargo run -- --source examples/web --watch```
|
* run ```cargo run -- --source examples/web --watch```
|
||||||
|
* see ```main.tp``` for the database queries
|
||||||
* and head to http://localhost:3000/api/customer
|
* and head to http://localhost:3000/api/customer
|
||||||
* optionally, adjust the database ddl, update the query in db.tp, and recheck the outpout
|
* optionally, adjust the database ddl, update the query in db.tp, and recheck the outpout
|
||||||
3
examples/web/main.tp
Normal file
3
examples/web/main.tp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
println("Creating the customers table")
|
||||||
|
sql("create table if not exists customers(id serial primary key, first_name varchar(50), last_name varchar(50))")
|
||||||
|
sql("insert into customers (first_name,last_name) values ('first', 'last')")
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use log::info;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
use crate::{symbol_builder, AsmRegistry, TIPI_EXT};
|
use crate::{symbol_builder, AsmRegistry, TIPI_EXT};
|
||||||
use crate::compiler::assembly_pass::AsmChunk;
|
use crate::compiler::assembly_pass::AsmChunk;
|
||||||
|
|
@ -20,7 +21,7 @@ pub fn compile_sourcedir(source_dir: &str) -> Result<HashMap<String, AsmChunk>,
|
||||||
for entry in WalkDir::new(source_dir).into_iter().filter_map(|e| e.ok()) {
|
for entry in WalkDir::new(source_dir).into_iter().filter_map(|e| e.ok()) {
|
||||||
let path = entry.path().to_str().unwrap();
|
let path = entry.path().to_str().unwrap();
|
||||||
if path.ends_with(TIPI_EXT) {
|
if path.ends_with(TIPI_EXT) {
|
||||||
println!("-- Compiling {} -- ", path);
|
info!("-- Compiling {} -- ", path);
|
||||||
let source = fs::read_to_string(path).map_err(map_underlying())?;
|
let source = fs::read_to_string(path).map_err(map_underlying())?;
|
||||||
let tokens = scan_pass::scan(&source)?;
|
let tokens = scan_pass::scan(&source)?;
|
||||||
match ast_pass::compile(Some(path), tokens, &mut symbol_table) {
|
match ast_pass::compile(Some(path), tokens, &mut symbol_table) {
|
||||||
|
|
@ -64,5 +65,5 @@ pub fn run(src: &str) -> Result<crate::value::Value, TipiLangError> {
|
||||||
let mut asm_registry = HashMap::new();
|
let mut asm_registry = HashMap::new();
|
||||||
assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?;
|
assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?;
|
||||||
let registry = arc_swap::ArcSwap::from(std::sync::Arc::new(asm_registry));
|
let registry = arc_swap::ArcSwap::from(std::sync::Arc::new(asm_registry));
|
||||||
crate::vm::interpret(registry.load(), "main").map_err(TipiLangError::from)
|
crate::vm::run(registry.load(), "main").map_err(TipiLangError::from)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,13 @@ pub fn start_watch_daemon(source: &str, registry: Arc<ArcSwap<HashMap<String, As
|
||||||
let s = source.to_string();
|
let s = source.to_string();
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
println!("-- File watch started --");
|
info!("-- File watch started --");
|
||||||
let path = Path::new(&source);
|
let path = Path::new(&source);
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
panic!("source directory {} does not exist", &source);
|
panic!("source directory {} does not exist", &source);
|
||||||
}
|
}
|
||||||
let mut watcher = notify::recommended_watcher(tx).expect("Failed to create watcher");
|
let mut watcher = notify::recommended_watcher(tx)
|
||||||
|
.expect("Failed to create watcher");
|
||||||
watcher
|
watcher
|
||||||
.watch(path, RecursiveMode::Recursive)
|
.watch(path, RecursiveMode::Recursive)
|
||||||
.expect("Failed to watch");
|
.expect("Failed to watch");
|
||||||
|
|
|
||||||
29
src/main.rs
29
src/main.rs
|
|
@ -5,17 +5,17 @@ use axum::routing::any;
|
||||||
use axum::{Json, Router};
|
use axum::{Json, Router};
|
||||||
use bb8_postgres::PostgresConnectionManager;
|
use bb8_postgres::PostgresConnectionManager;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use log::info;
|
use log::{error, info};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::{Arc, LazyLock, OnceLock};
|
use std::sync::{Arc, LazyLock, OnceLock};
|
||||||
use tipi_lang::compiler::assembly_pass::AsmChunk;
|
use tipi_lang::compiler::assembly_pass::AsmChunk;
|
||||||
use tipi_lang::compiler::{compile_sourcedir, map_underlying, run};
|
use tipi_lang::compiler::{compile_sourcedir, map_underlying, run};
|
||||||
use tipi_lang::errors::TipiLangError;
|
use tipi_lang::errors::TipiLangError;
|
||||||
use tipi_lang::vm::interpret_async;
|
|
||||||
use tokio_postgres::NoTls;
|
|
||||||
use tipi_lang::DB_POOL;
|
|
||||||
use tipi_lang::value::Value;
|
use tipi_lang::value::Value;
|
||||||
|
use tipi_lang::vm::run_async;
|
||||||
|
use tipi_lang::{DB_POOL, vm};
|
||||||
|
use tokio_postgres::NoTls;
|
||||||
|
|
||||||
/// A simple CLI tool to greet users
|
/// A simple CLI tool to greet users
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
|
@ -36,8 +36,10 @@ struct Args {
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), TipiLangError> {
|
async fn main() -> Result<(), TipiLangError> {
|
||||||
//TODO make configurable
|
//TODO make configurable
|
||||||
let manager =
|
let manager = PostgresConnectionManager::new_from_stringlike(
|
||||||
PostgresConnectionManager::new_from_stringlike("host=localhost user=postgres password=boompje", NoTls)
|
"host=localhost user=postgres password=boompje",
|
||||||
|
NoTls,
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let pool = bb8::Pool::builder()
|
let pool = bb8::Pool::builder()
|
||||||
.build(manager)
|
.build(manager)
|
||||||
|
|
@ -51,17 +53,22 @@ async fn main() -> Result<(), TipiLangError> {
|
||||||
let source = fs::read_to_string(file).expect("Unable to read file");
|
let source = fs::read_to_string(file).expect("Unable to read file");
|
||||||
run(&source)?;
|
run(&source)?;
|
||||||
} else {
|
} else {
|
||||||
println!("-- Tipilang --");
|
info!("-- Tipilang --");
|
||||||
let source = args.source.unwrap_or("./source".to_string());
|
let source = args.source.unwrap_or("./source".to_string());
|
||||||
let registry = compile_sourcedir(&source)?;
|
let registry = compile_sourcedir(&source)?;
|
||||||
let empty = registry.is_empty();
|
let empty = registry.is_empty();
|
||||||
|
|
||||||
let swap = Arc::new(ArcSwap::from(Arc::new(registry)));
|
let swap = Arc::new(ArcSwap::from(Arc::new(registry)));
|
||||||
if !empty {
|
if !empty {
|
||||||
|
let registry = swap.clone().load();
|
||||||
|
if let Some(main) = registry.get("/main") {
|
||||||
|
vm::run(registry, "/main")?;
|
||||||
|
}
|
||||||
|
|
||||||
if args.watch {
|
if args.watch {
|
||||||
tipi_lang::file_watch::start_watch_daemon(&source, swap.clone());
|
tipi_lang::file_watch::start_watch_daemon(&source, swap.clone());
|
||||||
}
|
}
|
||||||
println!("-- Compilation successful --");
|
info!("-- Compilation successful --");
|
||||||
let state = AppState {
|
let state = AppState {
|
||||||
registry: swap.clone(),
|
registry: swap.clone(),
|
||||||
};
|
};
|
||||||
|
|
@ -73,7 +80,7 @@ async fn main() -> Result<(), TipiLangError> {
|
||||||
.await
|
.await
|
||||||
.map_err(map_underlying())?;
|
.map_err(map_underlying())?;
|
||||||
|
|
||||||
println!(
|
info!(
|
||||||
"-- Listening on {} --\n",
|
"-- Listening on {} --\n",
|
||||||
listener.local_addr().map_err(map_underlying())?
|
listener.local_addr().map_err(map_underlying())?
|
||||||
);
|
);
|
||||||
|
|
@ -84,7 +91,7 @@ async fn main() -> Result<(), TipiLangError> {
|
||||||
|
|
||||||
axum::serve(listener, app).await.map_err(map_underlying())?;
|
axum::serve(listener, app).await.map_err(map_underlying())?;
|
||||||
} else {
|
} else {
|
||||||
println!("No source files found or compilation error");
|
error!("No source files found or compilation error");
|
||||||
if args.repl {
|
if args.repl {
|
||||||
tipi_lang::repl::start(swap.clone())?;
|
tipi_lang::repl::start(swap.clone())?;
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +130,7 @@ async fn handle_any(
|
||||||
}
|
}
|
||||||
let path = &req.uri().to_string();
|
let path = &req.uri().to_string();
|
||||||
info!("invoked {:?} => {}", req, function_qname);
|
info!("invoked {:?} => {}", req, function_qname);
|
||||||
match interpret_async(
|
match run_async(
|
||||||
state.registry.load(),
|
state.registry.load(),
|
||||||
&function_qname,
|
&function_qname,
|
||||||
path,
|
path,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub async fn interpret_async(
|
pub async fn run_async(
|
||||||
registry: Guard<Arc<HashMap<String, AsmChunk>>>,
|
registry: Guard<Arc<HashMap<String, AsmChunk>>>,
|
||||||
function: &str,
|
function: &str,
|
||||||
uri: &str,
|
uri: &str,
|
||||||
|
|
@ -38,13 +38,13 @@ pub async fn interpret_async(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret(registry: Guard<Arc<AsmRegistry>>, function: &str) -> Result<Value, RuntimeError> {
|
pub fn run(registry: Guard<Arc<AsmRegistry>>, function: &str) -> Result<Value, RuntimeError> {
|
||||||
let chunk = registry.get(function).unwrap().clone();
|
let chunk = registry.get(function).unwrap().clone();
|
||||||
let mut vm = Vm::new(®istry);
|
let mut vm = Vm::new(®istry);
|
||||||
vm.run(&get_context(function), &chunk)
|
vm.run(&get_context(function), &chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret_function(chunk: &AsmChunk, args: Vec<Value>, registry: Arc<AsmRegistry>) -> Result<Value, RuntimeError> {
|
pub fn run_function(chunk: &AsmChunk, args: Vec<Value>, registry: Arc<AsmRegistry>) -> Result<Value, RuntimeError> {
|
||||||
let mut vm = Vm::new(®istry);
|
let mut vm = Vm::new(®istry);
|
||||||
vm.run_function(chunk, args)
|
vm.run_function(chunk, args)
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +241,7 @@ impl Vm {
|
||||||
return Err(RuntimeError::FunctionNotFound(function_name));
|
return Err(RuntimeError::FunctionNotFound(function_name));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let result = interpret_function(function_chunk.unwrap(), args, self.registry.clone())?;
|
let result = run_function(function_chunk.unwrap(), args, self.registry.clone())?;
|
||||||
self.push(Rc::new(RefCell::new(result)));
|
self.push(Rc::new(RefCell::new(result)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue