added main.tp entrypoint

This commit is contained in:
Shautvast 2026-01-13 21:29:45 +01:00
parent 215dc13797
commit 05279201c8
7 changed files with 33 additions and 36 deletions

View file

@ -235,7 +235,3 @@ ISSUES
* improve indenting
WIP guards
* | /$uuid -> service.get(uuid)?
| /&first_name -> service.get_by_firstname(first_name)?
| /&last_name -> service.get_by_lastname(last_name)?
| 404

View file

@ -1,18 +1,7 @@
* currently needs postgres on the default port
* user 'postgres'
* 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```
* see ```main.tp``` for the database queries
* and head to http://localhost:3000/api/customer
* optionally, adjust the database ddl, update the query in db.tp, and recheck the outpout

3
examples/web/main.tp Normal file
View 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')")

View file

@ -1,5 +1,6 @@
use std::collections::HashMap;
use std::fs;
use log::info;
use walkdir::WalkDir;
use crate::{symbol_builder, AsmRegistry, TIPI_EXT};
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()) {
let path = entry.path().to_str().unwrap();
if path.ends_with(TIPI_EXT) {
println!("-- Compiling {} -- ", path);
info!("-- Compiling {} -- ", path);
let source = fs::read_to_string(path).map_err(map_underlying())?;
let tokens = scan_pass::scan(&source)?;
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();
assembly_pass::compile(None, &ast, &symbol_table, &mut 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)
}

View file

@ -17,12 +17,13 @@ pub fn start_watch_daemon(source: &str, registry: Arc<ArcSwap<HashMap<String, As
let s = source.to_string();
let (tx, rx) = channel();
thread::spawn(move || {
println!("-- File watch started --");
info!("-- File watch started --");
let path = Path::new(&source);
if !path.exists() {
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
.watch(path, RecursiveMode::Recursive)
.expect("Failed to watch");

View file

@ -5,17 +5,17 @@ use axum::routing::any;
use axum::{Json, Router};
use bb8_postgres::PostgresConnectionManager;
use clap::Parser;
use log::info;
use log::{error, info};
use std::collections::HashMap;
use std::fs;
use std::sync::{Arc, LazyLock, OnceLock};
use tipi_lang::compiler::assembly_pass::AsmChunk;
use tipi_lang::compiler::{compile_sourcedir, map_underlying, run};
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::vm::run_async;
use tipi_lang::{DB_POOL, vm};
use tokio_postgres::NoTls;
/// A simple CLI tool to greet users
#[derive(Parser, Debug)]
@ -36,8 +36,10 @@ struct Args {
#[tokio::main]
async fn main() -> Result<(), TipiLangError> {
//TODO make configurable
let manager =
PostgresConnectionManager::new_from_stringlike("host=localhost user=postgres password=boompje", NoTls)
let manager = PostgresConnectionManager::new_from_stringlike(
"host=localhost user=postgres password=boompje",
NoTls,
)
.unwrap();
let pool = bb8::Pool::builder()
.build(manager)
@ -51,17 +53,22 @@ async fn main() -> Result<(), TipiLangError> {
let source = fs::read_to_string(file).expect("Unable to read file");
run(&source)?;
} else {
println!("-- Tipilang --");
info!("-- Tipilang --");
let source = args.source.unwrap_or("./source".to_string());
let registry = compile_sourcedir(&source)?;
let empty = registry.is_empty();
let swap = Arc::new(ArcSwap::from(Arc::new(registry)));
if !empty {
let registry = swap.clone().load();
if let Some(main) = registry.get("/main") {
vm::run(registry, "/main")?;
}
if args.watch {
tipi_lang::file_watch::start_watch_daemon(&source, swap.clone());
}
println!("-- Compilation successful --");
info!("-- Compilation successful --");
let state = AppState {
registry: swap.clone(),
};
@ -73,7 +80,7 @@ async fn main() -> Result<(), TipiLangError> {
.await
.map_err(map_underlying())?;
println!(
info!(
"-- Listening on {} --\n",
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())?;
} else {
println!("No source files found or compilation error");
error!("No source files found or compilation error");
if args.repl {
tipi_lang::repl::start(swap.clone())?;
}
@ -123,7 +130,7 @@ async fn handle_any(
}
let path = &req.uri().to_string();
info!("invoked {:?} => {}", req, function_qname);
match interpret_async(
match run_async(
state.registry.load(),
&function_qname,
path,

View file

@ -10,7 +10,7 @@ use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
pub async fn interpret_async(
pub async fn run_async(
registry: Guard<Arc<HashMap<String, AsmChunk>>>,
function: &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 mut vm = Vm::new(&registry);
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(&registry);
vm.run_function(chunk, args)
}
@ -241,7 +241,7 @@ impl Vm {
return Err(RuntimeError::FunctionNotFound(function_name));
}
} 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)));
}
}