diff --git a/mapgen/go.mod b/mapgen/go.mod deleted file mode 100644 index 787464e..0000000 --- a/mapgen/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module mapgen - -go 1.25.5 - -require ( - golang.org/x/mod v0.35.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/tools v0.44.0 // indirect -) diff --git a/mapgen/go.sum b/mapgen/go.sum deleted file mode 100644 index d570929..0000000 --- a/mapgen/go.sum +++ /dev/null @@ -1,6 +0,0 @@ -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= diff --git a/mapgen/main.go b/mapgen/main.go deleted file mode 100644 index b51fad5..0000000 --- a/mapgen/main.go +++ /dev/null @@ -1,188 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "go/token" - "go/types" - "os" - "unicode" - - "golang.org/x/tools/go/packages" -) - -type TypeSymbol string - -type VarSymbol struct { - Export bool `json:"export"` - VarType TypeSymbol `json:"var_type"` - Name string `json:"name"` -} - -type FunctionSymbol struct { - Export bool `json:"export"` - Name string `json:"name"` - Params map[string]VarSymbol `json:"params"` - ReturnTypes []TypeSymbol `json:"return_types"` -} - -type StructSymbol struct { - Export bool `json:"export"` - Name string `json:"name"` - Fields map[string]VarSymbol `json:"fields"` - Methods map[string]FunctionSymbol `json:"methods"` -} - -type TopLevelSymbolScope struct { - PackageName string `json:"package_name"` - Structs map[string]StructSymbol `json:"structs"` - Functions map[string]FunctionSymbol `json:"functions"` -} - -func main() { - cfg := &packages.Config{ - Mode: packages.NeedName | - packages.NeedTypes | - packages.NeedTypesInfo | - packages.NeedModule, - } - - // you can expand this to multiple packages later - pkgs, err := packages.Load(cfg, "fmt") - if err != nil { - panic(err) - } - - if packages.PrintErrors(pkgs) > 0 { - os.Exit(1) - } - - // 🔑 FINAL RESULT: map[import_path]scope - result := make(map[string]TopLevelSymbolScope) - - for _, pkg := range pkgs { - scopeData := TopLevelSymbolScope{ - PackageName: pkg.Name, // e.g. "http" - Structs: make(map[string]StructSymbol), - Functions: make(map[string]FunctionSymbol), - } - - scope := pkg.Types.Scope() - - for _, name := range scope.Names() { - if !token.IsExported(name) { - continue - } - - obj := scope.Lookup(name) - - switch obj := obj.(type) { - - case *types.Func: - scopeData.Functions[LowerFirst(name)] = buildFunction(obj) - - case *types.TypeName: - if strct, ok := buildStruct(obj); ok { - scopeData.Structs[name] = strct - } - } - } - - // 🔑 key = import path (e.g. "net/http") - result[pkg.PkgPath] = scopeData - } - - out, err := json.MarshalIndent(result, "", " ") - if err != nil { - panic(err) - } - - fmt.Println(string(out)) -} - -func LowerFirst(s string) string { - if s == "" { - return "" - } - r := []rune(s) - r[0] = unicode.ToLower(r[0]) - return string(r) -} - -func buildFunction(fn *types.Func) FunctionSymbol { - sig := fn.Type().(*types.Signature) - - params := make(map[string]VarSymbol) - for i := 0; i < sig.Params().Len(); i++ { - p := sig.Params().At(i) - - name := p.Name() - if name == "" { - name = fmt.Sprintf("param%d", i) - } - - params[name] = VarSymbol{ - Export: true, - Name: name, - VarType: TypeSymbol(p.Type().String()), - } - } - - var returnTypes []TypeSymbol - for i := 0; i < sig.Results().Len(); i++ { - r := sig.Results().At(i) - returnTypes = append(returnTypes, TypeSymbol(r.Type().String())) - } - - return FunctionSymbol{ - Export: true, // already filtered before calling - Name: fn.Name(), - Params: params, - ReturnTypes: returnTypes, - } -} - -func buildStruct(tn *types.TypeName) (StructSymbol, bool) { - underlying := tn.Type().Underlying() - - strct, ok := underlying.(*types.Struct) - if !ok { - return StructSymbol{}, false - } - - fields := make(map[string]VarSymbol) - - for i := 0; i < strct.NumFields(); i++ { - f := strct.Field(i) - - if !token.IsExported(f.Name()) { - continue - } - - fields[f.Name()] = VarSymbol{ - Export: true, - Name: f.Name(), - VarType: TypeSymbol(f.Type().String()), - } - } - - methods := make(map[string]FunctionSymbol) - methodSet := types.NewMethodSet(tn.Type()) - - for i := 0; i < methodSet.Len(); i++ { - m := methodSet.At(i).Obj().(*types.Func) - - if !token.IsExported(m.Name()) { - continue - } - - methods[LowerFirst(m.Name())] = buildFunction(m) - } - - return StructSymbol{ - Export: true, - Name: tn.Name(), - Fields: fields, - Methods: methods, - }, true -} diff --git a/parser/src/script_grammar.pest b/parser/src/script_grammar.pest deleted file mode 100644 index 5ba90bc..0000000 --- a/parser/src/script_grammar.pest +++ /dev/null @@ -1,123 +0,0 @@ -WHITESPACE = _{ " " | "\t" | "\r" | "\n" } -COMMENT = _{ "//" ~ (!"\n" ~ ANY)* } - -program = { SOI ~ top_level* ~ EOI } - -// primitives -identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } -integer = @{ ASCII_DIGIT+ } -float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } -boolean = { "true" | "false" } -string_lit = { "\"" ~ inner_str ~ "\"" } -inner_str = @{ (!"\"" ~ ANY)* } - -// ================= TOP LEVEL ================= - -top_level = _{ import | function_decl | struct_decl | package } - -package = { "package" ~ identifier ~ ";" } - -export = { "export" } - -import = { "import" ~ string_lit ~ ";" } - -param_list = { param ~ ("," ~ param)* ~ ","? } -param = { export? ~ identifier ~ ":" ~ type_expr } - -struct_decl = { - export? ~ "struct" ~ identifier ~ "{" ~ param_list? ~ "}" -} - -function_decl = { - export? ~ "function" ~ identifier ~ "(" ~ param_list? ~ ")" ~ (":" ~ type_expr)? ~ block -} - -// ================= STATEMENTS ================= - -block = { "{" ~ statement_list ~ "}" } - -statement_list = { statement* } - -statement = _{ - expr_stmt - | var_decl - | var_assign - | if_stmt - | while_stmt - | for_stmt - | return_stmt - | break_stmt - | continue_stmt - | block -} - -// --- basic statements --- - -expr_stmt = { expr ~ ";" } - -return_stmt = { "return" ~ expr? ~ ";" } - -break_stmt = { "break" ~ ";" } - -continue_stmt = { "continue" ~ ";" } - -// --- variable declarations --- - -var_decl_kind = { "let" | "const" | "var" } - -var_decl = { - var_decl_kind ~ identifier ~ ("=" ~ expr)? ~ ";" -} - -var_assign = { - expr ~ "=" ~ expr ~ ";" -} - -// --- control flow --- - -if_stmt = { - "if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)? -} - -while_stmt = { - "while" ~ "(" ~ expr ~ ")" ~ statement -} - -for_stmt = { - "for" ~ "(" ~ var_decl ~ expr ~ ";" ~ var_assign_no_semicolon ~ ")" ~ statement -} - -var_assign_no_semicolon = { - expr ~ "=" ~ expr -} - -// ================= EXPRESSIONS ================= -type_expr = { identifier } - -primary = { - integer - | float - | boolean - | string_lit - | identifier -} - -postfix = { - field_px - | call_px - | struct_px - | index_px - | binary_px -} - -field_px = { "." ~ identifier } -call_px = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } -struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ "}" } -index_px = { "[" ~ expr ~ "]" } -binary_px = { bin_op ~ expr } -bin_op = { "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" } -struct_field_decl = { identifier ~ ":" ~ expr } - -expr = { - primary ~ postfix* -} diff --git a/parser/src/script_parser.rs b/parser/src/script_parser.rs deleted file mode 100644 index cff3b6f..0000000 --- a/parser/src/script_parser.rs +++ /dev/null @@ -1,388 +0,0 @@ -use std::collections::HashMap; - -use pest::Parser; -use pest_derive::Parser; - -use crate::ast::*; - -#[derive(Parser)] -#[grammar = "./src/script_grammar.pest"] -pub struct MistScriptParser; - -// convenience alias for pest errors -pub type ParseError = pest::error::Error; - -pub fn parse(source: &str) -> Result, ParseError> { - let mut pairs = MistScriptParser::parse(Rule::program, source)?; - - let mut statements = vec![]; - - for pair in pairs.next().unwrap().into_inner() { - if let Ok(stmt) = TopLevel::try_from(pair) { - statements.push(stmt); - } - } - - Ok(statements) -} - -impl From> for TypeExpr { - fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { - Rule::type_expr => { - let inner = pair.into_inner().next().unwrap(); - TypeExpr::from(inner) - } - Rule::identifier => TypeExpr::Identifier(pair.as_str().to_string()), - _ => unimplemented!("TypeExpr parsing not implemented yet"), - } - } -} - -impl From<(bool, pest::iterators::Pair<'_, Rule>)> for ParamList { - fn from((export_allowed, pair): (bool, pest::iterators::Pair)) -> Self { - let params = pair - .into_inner() - .map(|p| { - let mut param_inner = p.into_inner(); - let export = - if export_allowed && param_inner.peek().unwrap().as_rule() == Rule::export { - param_inner.next().unwrap(); - true - } else { - false - }; - let param_name = param_inner.next().unwrap().as_str().to_string(); - let param_type = TypeExpr::from(param_inner.next().unwrap()); - (param_name, (export, param_type)) - }) - .collect(); - - ParamList(params) - } -} - -impl TryFrom> for TopLevel { - type Error = (); - fn try_from(pair: pest::iterators::Pair) -> Result { - match pair.as_rule() { - Rule::import => { - let path = pair.into_inner().next().unwrap().as_str().to_string(); - Ok(TopLevel::Import(path)) - } - Rule::package => { - let name = pair.into_inner().next().unwrap().as_str().to_string(); - Ok(TopLevel::Package(name)) - } - Rule::function_decl => { - let mut inner = pair.into_inner(); - - let export = if let Some(first) = inner.peek() { - if first.as_rule() == Rule::export { - inner.next(); - true - } else { - false - } - } else { - false - }; - let name = inner.next().unwrap().as_str().to_string(); - let params = if inner.peek().unwrap().as_rule() == Rule::param_list { - ParamList::from((false, inner.next().unwrap())) - } else { - ParamList(HashMap::new()) - }; - let return_type = if let Some(next) = inner.peek() { - if next.as_rule() == Rule::type_expr { - Some(TypeExpr::from(inner.next().unwrap())) - } else { - None - } - } else { - None - }; - - let body = Block::from(inner.next().unwrap()); - - Ok(TopLevel::FunctionDecl { - export, - name, - params, - return_type, - body, - }) - } - - Rule::struct_decl => { - let mut inner = pair.into_inner(); - let export = if let Some(first) = inner.peek() { - if first.as_rule() == Rule::export { - inner.next(); - true - } else { - false - } - } else { - false - }; - let name = inner.next().unwrap().as_str().to_string(); - let fields_pair = inner.next().unwrap(); - let fields = ParamList::from((true, fields_pair)); - - Ok(TopLevel::StructDecl { - export, - name, - fields, - }) - } - - Rule::EOI => Err(()), - _ => unimplemented!("TopLevel parsing not implemented yet {:?}", pair.as_rule()), - } - } -} - -impl From> for Block { - fn from(pair: pest::iterators::Pair) -> Self { - let statements = pair - .into_inner() - .flat_map(|pair| { - if pair.as_rule() == Rule::statement_list { - pair.into_inner().map(Statement::from).collect() - } else { - vec![Statement::from(pair)] - } - }) - .collect(); - Block(statements) - } -} - -impl From> for Statement { - fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { - Rule::statement => { - let inner = pair.into_inner().next().unwrap(); - Statement::from(inner) - } - - Rule::expr_stmt => { - let expr_pair = pair.into_inner().next().unwrap(); - Statement::Expression(Expression::from(expr_pair)) - } - - Rule::block => Statement::Block(Block::from(pair.into_inner().next().unwrap())), - - Rule::var_decl => { - let mut inner = pair.into_inner(); - - let kind_pair = inner.next().unwrap(); // let/const/var - let name_pair = inner.next().unwrap(); // identifier - - let init = inner.next().map(Expression::from); - - let kind = match kind_pair.as_str() { - "let" => VarKind::Let, - "const" => VarKind::Const, - "var" => VarKind::Var, - _ => unreachable!(), - }; - - Statement::VarDecl { - kind, - name: name_pair.as_str().to_string(), - init, - type_: None, - } - } - - Rule::return_stmt => { - let mut inner = pair.into_inner(); - - let expr = inner.next().map(Expression::from); - - Statement::Return(expr) - } - - Rule::break_stmt => Statement::Break, - - Rule::continue_stmt => Statement::Continue, - - Rule::if_stmt => { - let mut inner = pair.into_inner(); - - let condition = Expression::from(inner.next().unwrap()); - let then_branch = Statement::from(inner.next().unwrap()); - - let else_branch = inner.next().map(Statement::from); - - Statement::If { - condition, - then_branch: Box::new(then_branch), - else_branch: else_branch.map(Box::new), - } - } - - Rule::while_stmt => { - let mut inner = pair.into_inner(); - - let condition = Expression::from(inner.next().unwrap()); - let body = Statement::from(inner.next().unwrap()); - - Statement::While { - condition, - body: Box::new(body), - } - } - - Rule::for_stmt => { - let mut inner = pair.into_inner(); - - let init = inner - .next() - .map(|p| match p.as_rule() { - Rule::var_decl => { - let mut it = p.into_inner(); - - let kind = match it.next().unwrap().as_str() { - "let" => VarKind::Let, - "const" => VarKind::Const, - "var" => VarKind::Var, - _ => unreachable!(), - }; - - let name = it.next().unwrap().as_str().to_string(); - let init_expr = it - .next() - .map(|e| Expression::from(e.into_inner().next().unwrap())); - - (kind, name, init_expr) - } - _ => unimplemented!( - "For loop init parsing not implemented yet: {:?}", - p.as_rule() - ), - }) - .unwrap(); - - let condition = inner.next().map(Expression::from); - let update = inner.next().map(parse_var_assign_no_semicolon); - let body = Statement::from(inner.next().unwrap()); - - Statement::For { - init, - condition, - update: update.map(Box::new), - body: Box::new(body), - } - } - - Rule::var_assign => { - let mut inner = pair.into_inner(); - let target = Expression::from(inner.next().unwrap()); - let value = Expression::from(inner.next().unwrap()); - - Statement::VarAssign { target, value } - } - - _ => unimplemented!( - "Statement parsing not implemented yet: {:?}", - pair.as_rule() - ), - } - } -} - -impl From> for Expression { - fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { - Rule::expr => { - let mut inner = pair.into_inner(); - let exp = Expression::from(inner.next().unwrap()); - - if inner.len() > 0 { - Expression::Postfix { - initial: Box::new(exp), - postfixes: inner.map(|p| Postfix::from(p)).collect(), - } - } else { - exp - } - } - Rule::primary => Expression::from(pair.into_inner().next().unwrap()), - Rule::identifier => Expression::Identifier(pair.as_str().to_string()), - Rule::integer => { - let value = pair.as_str().parse::().unwrap(); - Expression::IntLiteral(value) - } - Rule::float => { - let value = pair.as_str().parse::().unwrap(); - Expression::FloatLiteral(value) - } - Rule::boolean => { - let value = pair.as_str().parse::().unwrap(); - Expression::BoolLiteral(value) - } - Rule::string_lit => { - let inner_str = pair.into_inner().next().unwrap().as_str(); - Expression::StringLiteral(inner_str.to_string()) - } - - _ => unimplemented!( - "Expression parsing not implemented yet {:?}", - pair.as_rule() - ), - } - } -} - -impl From> for Postfix { - fn from(pair: pest::iterators::Pair) -> Self { - match pair.as_rule() { - Rule::postfix => Postfix::from(pair.into_inner().next().unwrap()), - - Rule::field_px => { - let field_name = pair.into_inner().next().unwrap().as_str().to_string(); - Postfix::FieldAccess(field_name) - } - - Rule::call_px => Postfix::Call(pair.into_inner().map(Expression::from).collect()), - - Rule::index_px => Postfix::Index(Expression::from(pair.into_inner().next().unwrap())), - - Rule::binary_px => { - let mut inner = pair.into_inner(); - let op_pair = inner.next().unwrap(); - let op = match op_pair.as_str() { - "+" => BinaryOp::Plus, - "-" => BinaryOp::Minus, - "*" => BinaryOp::Multiply, - "/" => BinaryOp::Divide, - "%" => BinaryOp::Modulo, - "==" => BinaryOp::Equal, - "!=" => BinaryOp::NotEqual, - "<" => BinaryOp::LessThan, - ">" => BinaryOp::GreaterThan, - "<=" => BinaryOp::LessThanOrEqual, - ">=" => BinaryOp::GreaterThanOrEqual, - - _ => { - unimplemented!("Binary operator not implemented yet: {}", op_pair.as_str()) - } - }; - Postfix::Binary(op, Expression::from(inner.next().unwrap())) - } - - _ => unimplemented!("Postfix parsing not implemented yet {:?}", pair.as_rule()), - } - } -} - -fn parse_var_assign_no_semicolon(pair: pest::iterators::Pair) -> Statement { - let mut inner = pair.into_inner(); - let target = Expression::from(inner.next().unwrap()); - let value = Expression::from(inner.next().unwrap()); - - Statement::VarAssign { target, value } -}