From c7515655a3cdf7e2a24f7cd91a8988d066f03bed Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 24 Dec 2024 22:48:22 -0600 Subject: [PATCH 1/3] making good progress on bootstrap token --- bootstrap/makefile | 5 + bootstrap/src/token.ty | 465 +++++++++++++++++++++++++++++++++++++++++ bootstrap/token/lib.ty | 461 ---------------------------------------- ebnf.txt | 6 +- lexer/src/lib.rs | 3 + linter/src/lib.rs | 3 +- parser/src/lib.rs | 21 +- token/src/lib.rs | 10 +- 8 files changed, 495 insertions(+), 479 deletions(-) create mode 100644 bootstrap/makefile create mode 100644 bootstrap/src/token.ty delete mode 100644 bootstrap/token/lib.ty diff --git a/bootstrap/makefile b/bootstrap/makefile new file mode 100644 index 0000000..17e328d --- /dev/null +++ b/bootstrap/makefile @@ -0,0 +1,5 @@ +.ty/token.o: + ty obj src/token.ty + +clean: + rm -rf .ty diff --git a/bootstrap/src/token.ty b/bootstrap/src/token.ty new file mode 100644 index 0000000..b9be4b9 --- /dev/null +++ b/bootstrap/src/token.ty @@ -0,0 +1,465 @@ +pub type TokenError = error + | InvalidToken + | UnexpectedEnd + +pub type Token = enum + | Error + | Defer + | ErrDefer + | Any + | Macro + | Import + | Test + | Bench + | Let + | Const + | Copy + | Clone + | Scalar + | Sized + | I32 + | U32 + | I64 + | U64 + | I16 + | U16 + | I8 + | U8 + | Bit + | F64 + | D64 + | F32 + | D32 + | D128 + | F128 + | ISize + | USize + | If + | Else + | Type + | Self + | Char + | Utf8 + | Utf16 + | Utf32 + | Utf64 + | Match + | While + | For + | Of + | In + | Break + | Tag + | Pub + | Return + | Await + | Async + | As + | Alias + | NoSuspend + | Suspend + | Resume + | Frame + | Trait + | Impl + | True + | False + | Void + | Never + | Bool + | Contract + | Comptime + | Func + | Struct + | Extern + | Export + | KeyOf + | TypeOf + | InstanceOf + | RangeOf + | Enum + | Try + | Catch + // end keywords + | Split + | Yield + | Arrow + | OParen + | CParen + | OBrace + | CBrace + | OBracket + | CBracket + | Range + | Elipses + | Period + | Comma + | Dollar + | Question + | Pound + | Colon + | SColon + | At + | Lt + | LtEq + | Gt + | GtEq + | FSlash + | BSlash + | Concat + | Plus + | Underscore + | Dash + | Asterisk + | Bar + | Ampersand + | Caret + | LShift + | RShift + | Tilde + | As + | NotAs + | OrAs + | XorAs + | LShiftAs + | RShiftAs + | AndLog + | OrLog + | NotEquality + | Equality + | Exclam + | Percent + | AddAs + | SubAs + | DivAs + | MulAs + | ModAs + | AndAs + | String + | Number + | Symbol + | Decimal + | NewLine + | Comment + | Wsp + +const keywords: [[char]] = [ + "error", + "defer", + "errdefer", + "any", + "macro", + "import", + "test", + "bench", + "let", + "const", + "copy", + "clone", + "scalar", + "sized", + "i32", + "u32", + "i64", + "u64", + "i16", + "u16", + "i8", + "u8", + "bit", + "f64", + "d64", + "f32", + "d32", + "d128", + "f128", + "isize", + "usize", + "if", + "else", + "type", + "self", + "char", + "utf8", + "utf16", + "utf32", + "utf64", + "match", + "while", + "for", + "of", + "in", + "break", + "tag", + "pub", + "return", + "await", + "async", + "as", + "alias", + "nosuspend", + "suspend", + "resume", + "frame", + "trait", + "impl", + "true", + "false", + "void", + "never", + "bool", + "contract", + "comptime", + "func", + "struct", + "extern", + "export", + "keyof", + "typeof", + "instanceof", + "rangeof", + "enum", + "try", + "catch" + ] + +pub const get_next = fn(buf: &[char], len: *u32) TokenError!Token { + len = 0 + const c = buf[0] + return match (c) { + c.isAlphabetic() => tokenize_chars(buf, len) + c.isDigit() => tokenize_num(buf, len) + _ => { + return match (c) { + ' ' => { + len = skip_whitespace(buf) + return Token.Wsp + } + '"' => { + return build_string(buf, len, '"') + } + "'" => { + return build_string(buf, len, '\'') + } + '`' => { + return build_string(buf, len, '`') + } + '(' => { + len = 1 + return Token.OParen + } + ')' => { + len = 1 + return Token.CParen + } + '{' => { + len = 1 + return Token.OBrace + } + '}' => { + len = 1 + return Token.CBrace + } + '[' => { + len = 1 + return Token.OBracket + } + ']' => { + len = 1 + return Token.CBracket + } + ',' => { + len = 1 + return Token.Comma + } + '$' => { + len = 1 + return Token.Dollar + } + '?' => { + len = 1 + return Token.Question + } + '#' => { + len = 1 + return Token.Pound + } + ':' => { + len = 1 + return Token.Colon + } + ';' => { + len = 1 + return Token.SColon + } + '\\' => { + len = 1 + return Token.BSlash + } + '/' => { + // Comment, DivAs + len = 1 + return Token.FSlash + } + '@' => { + len = 1 + return Token.FSlash + } + '_' => { + len = 1 + return Token.Underscore + } + '&' => { + // AndLog, AndAs + len = 1 + return Token.Ampersand + } + '~' => { + // NotAs + len = 1 + return Token.Tilde + } + '.' => { + // Range, Elipses + len = 1 + return Token.Period + } + '^' => { + // XorLog + len = 1 + return Token.Caret + } + '|' => { + // OrLog, OrAs, Split + len = 1 + return Token.Bar + } + '-' => { + // SubAs, Yield + len = 1 + return Token.Dash + } + '=' => { + // Equality, Arrow + len = 1 + return Token.As + } + '<' => { + // LeftShift, LeftShiftAs, LtEq + len = 1 + return Token.Lt + } + '>' => { + // GtEq, RightShift, RightShiftAs + len = 1 + return Token.Gt + } + '!' => { + // NotEquality + len = 1 + return Token.Exclam + } + '%' => { + // ModAs + len = 1 + return Token.Percent + } + '+' => { + // AddAs, Concat + len = 1 + return Token.Plus + } + '*' => { + // MulAs + len = 1 + return Token.Asterisk + } + '\r' => { + if (buf.len > 1) { + if (buf[1] == '\n') { + len = 2 + return Token.NewLine + } + } + len = 1 + return TokenError.InvalidToken + } + '\n' => { + len = 1 + return Token.NewLine + } + '\t' => { + len = skip_whitespace(buf) + return Token.Wsp + } + _ => { + return Token.InvalidToken + } + } + } + } +} + +const tokenize_chars = fn(buf: &[char], len: *u32) Token { + let token = Token.Symbol + len = word_len_check(buf) + const check = buf[0..len] + for (keywords) fn(word: [char], idx: u32) void { + if (word.len == len) { + if (word == check) { + token = idx as Token + break + } + } + } + return token +} + +const word_len_check = fn(buf: &[char]) u32 { + let len = 0 + while (buf.len != len) { + const c = buf[len] + match (c) { + c.isAlphaNumeric() => { len += 1 } + (c == '_' || c == '-') => { len += 1 } + _ => { break } + } + } + return len +} + +const skip_whitespace = fn(buf: &[char]) u32 { + let len = 0 + while (buf.len != len) { + const c = buf[len] + match (c) { + c == ' ' || c == '\t' || c == '\r' => { len += 1 } + _ => { break } + } + } + return len +} + +const build_string = fn(buf: &[char], len: *u32, end: char) TokenError!Token { + len = 1 + while (buf.len != len) { + const c = buf[len] + match (c) { + c == '\\' => { + len += 1 + if (buf.len == len + 1) { + return TokenError.UnexpectedEnd + } + } + c == end => { + len += 1 + break + } + _ => { len += 1 } + } + } + if (len == 1) { + return TokenError.UnexpectedEnd + } + return Token.String +} diff --git a/bootstrap/token/lib.ty b/bootstrap/token/lib.ty deleted file mode 100644 index 1903996..0000000 --- a/bootstrap/token/lib.ty +++ /dev/null @@ -1,461 +0,0 @@ -pub type TokenError = error - | InvalidToken - | UnexpectedEnd - -pub type Token = enum - | Error - | Defer - | ErrDefer - | Any - | Macro - | Import - | Test - | Bench - | Let - | Const - | Copy - | Clone - | Scalar - | Sized - | I32 - | U32 - | I64 - | U64 - | I16 - | U16 - | I8 - | U8 - | Bit - | F64 - | D64 - | F32 - | D32 - | D128 - | F128 - | ISize - | USize - | If - | Else - | Type - | Self - | Char - | Utf8 - | Utf16 - | Utf32 - | Utf64 - | Match - | While - | For - | Of - | In - | Break - | Tag - | Pub - | Return - | Await - | Async - | As - | Alias - | NoSuspend - | Suspend - | Resume - | Frame - | Trait - | Impl - | True - | False - | Void - | Never - | Bool - | Contract - | Comptime - | Func - | Struct - | Extern - | Export - | KeyOf - | TypeOf - | InstanceOf - | RangeOf - | Enum - | Try - | Catch - // end keywords - | Split - | Yield - | Arrow - | OParen - | CParen - | OBrace - | CBrace - | OBracket - | CBracket - | Range - | Elipses - | Period - | Comma - | Dollar - | Question - | Pound - | Colon - | SColon - | At - | Lt - | LtEq - | Gt - | GtEq - | FSlash - | BSlash - | Concat - | Plus - | Underscore - | Dash - | Asterisk - | Bar - | Ampersand - | Caret - | LShift - | RShift - | Tilde - | As - | NotAs - | OrAs - | XorAs - | LShiftAs - | RShiftAs - | AndLog - | OrLog - | NotEquality - | Equality - | Exclam - | Percent - | AddAs - | SubAs - | DivAs - | MulAs - | ModAs - | AndAs - | String - | Number - | Symbol - | Decimal - | NewLine - | Comment - | Wsp - -const keywords: [[char]] = [ - "error", - "defer", - "errdefer", - "any", - "macro", - "import", - "test", - "bench", - "let", - "const", - "copy", - "clone", - "scalar", - "sized", - "i32", - "u32", - "i64", - "u64", - "i16", - "u16", - "i8", - "u8", - "bit", - "f64", - "d64", - "f32", - "d32", - "d128", - "f128", - "isize", - "usize", - "if", - "else", - "type", - "self", - "char", - "utf8", - "utf16", - "utf32", - "utf64", - "match", - "while", - "for", - "of", - "in", - "break", - "tag", - "pub", - "return", - "await", - "async", - "as", - "alias", - "nosuspend", - "suspend", - "resume", - "frame", - "trait", - "impl", - "true", - "false", - "void", - "never", - "bool", - "contract", - "comptime", - "func", - "struct", - "extern", - "export", - "keyof", - "typeof", - "instanceof", - "rangeof", - "enum", - "try", - "catch", - ] - -pub const get_next = fn(buf: &[char], len: *u32) TokenError!Token { - len = 0 - const c = buf[0] - if (c.isAlphabetic()) { - return tokenize_chars(buf, len) - } else if (c.isDigit()) { - return tokenize_num(buf, len) - } else { - return match (c) { - ' ' => { - len = skip_whitespace(buf) - return Token.Wsp - }, - '"' => { - return build_string(buf, len, '"') - }, - '\'' => { - return build_string(buf, len, '\'') - }, - '`' => { - return build_string(buf, len, '`') - }, - '(' => { - len = 1 - return Token.OParen - }, - ')' => { - len = 1 - return Token.CParen - }, - '{' => { - len = 1 - return Token.OBrace - }, - '}' => { - len = 1 - return Token.CBrace - }, - '[' => { - len = 1 - return Token.OBracket - }, - ']' => { - len = 1 - return Token.CBracket - }, - ',' => { - len = 1 - return Token.Comma - }, - '$' => { - len = 1 - return Token.Dollar - }, - '?' => { - len = 1 - return Token.Question - }, - '#' => { - len = 1 - return Token.Pound - }, - ':' => { - len = 1 - return Token.Colon - }, - ';' => { - len = 1 - return Token.SColon - }, - '\\' => { - len = 1 - return Token.BSlash - }, - '/' => { - // Comment, DivAs - len = 1 - return Token.FSlash - }, - '@' => { - len = 1 - return Token.FSlash - }, - '_' => { - len = 1 - return Token.Underscore - }, - '&' => { - // AndLog, AndAs - len = 1 - return Token.Ampersand - }, - '~' => { - // NotAs - len = 1 - return Token.Tilde - }, - '.' => { - // Range, Elipses - len = 1 - return Token.Period - }, - '^' => { - // XorLog - len = 1 - return Token.Caret - }, - '|' => { - // OrLog, OrAs, Split - len = 1 - return Token.Bar - }, - '-' => { - // SubAs, Yield - len = 1 - return Token.Dash - }, - '=' => { - // Equality, Arrow - len = 1 - return Token.As - }, - '<' => { - // LeftShift, LeftShiftAs, LtEq - len = 1 - return Token.Lt - }, - '>' => { - // GtEq, RightShift, RightShiftAs - len = 1 - return Token.Gt - }, - '!' => { - // NotEquality - len = 1 - return Token.Exclam - }, - '%' => { - // ModAs - len = 1 - return Token.Percent - }, - '+' => { - // AddAs, Concat - len = 1 - return Token.Plus - }, - '*' => { - // MulAs - len = 1 - return Token.Asterisk - }, - '\r' => { - if (buf.len > 1) { - if (buf[1] == '\n') { - len = 2 - return Token.NewLine - } - } - len = 1 - return TokenError.InvalidToken - }, - '\n' => { - len = 1 - return Token.NewLine - }, - '\t' => { - len = skip_whitespace(buf) - return Token.Wsp - }, - _ => { - return Token.InvalidToken - } - } - } - return TokenError.InvalidToken -} - -const tokenize_chars = fn(buf: &[char], len: *u32) Token { - let token = Token.Symbol - len = word_len_check(buf) - const check = buf[0..len] - for (keywords) fn(word, idx) void { - if (word.len == len) { - if (word == check) { - token = idx as Token - break - } - } - } - return token -} - -const word_len_check = fn(buf: &[char]) u32 { - let len = 0 - while (buf.len != len) { - const c = buf[len] - if (c.isAlphaNumeric()) { - len += 1 - } else if (c == '_' || c == '-') { - len += 1 - } else { break } - } - return len -} - -const skip_whitespace = fn(buf: &[char]) u32 { - let len = 0 - while (buf.len != len) { - const c = buf[len] - if (c == ' ' || c == '\t' || c == '\r') { - len += 1 - } else { break } - } - return len -} - -const build_string = fn(buf: &[char], len: *u32, end: char) TokenError!Token { - len = 1 - while (buf.len != len) { - const c = buf[len] - if (c == '\\') { - len += 1 - if (buf.len == len + 1) { - return TokenError.UnexpectedEnd - } - } else if (c == end) { - len += 1 - break - } else { len += 1 } - } - if (len == 1) { - return TokenError.UnexpectedEnd - } - return Token.String -} diff --git a/ebnf.txt b/ebnf.txt index b818c8b..b25e242 100644 --- a/ebnf.txt +++ b/ebnf.txt @@ -11,7 +11,9 @@ ::= "fn " "(" ? ") " ::= "struct " "{ " ? "}" ::= "error " ("| " )+ - ::= "if " "(" ")" ( | ) + ::= "if " "(" ")" ( | ) * ? + ::= "else " "if " "(" ")" ( | ) + ::= "else " ( | ) ::= "for " "(" ")" ( | ) ::= "while " "(" ")" ( | ) ::= "match " "(" ")" "{ " + "}" @@ -25,7 +27,7 @@ ::= ("self " (": " )?) | (":" )? ::= ( "const " | "let ") (":" )? "= " ::= ("= " )? - ::= "{ " ( | | | | )* ( | )? "}" + ::= "{ " ( | | | | | )* ( | )? "}" ::= "return " ? ::= "break " ? ::= | | diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index 417a4ed..ff6ffe5 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -37,6 +37,9 @@ impl<'s> TLexer<'s> { if self.current.is_none() { match self.lexer.next() { Some(val) => { + if val.is_err() { + return None; + } self.current = Some(Lexeme { token: val.unwrap(), span: self.lexer.span(), diff --git a/linter/src/lib.rs b/linter/src/lib.rs index d280d7f..b38a9ef 100644 --- a/linter/src/lib.rs +++ b/linter/src/lib.rs @@ -300,12 +300,13 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { let mut curried = Ty::Unknown; match _vt.val.token { Token::U64 => curried = Ty::U64, + Token::U32 => curried = Ty::U32, Token::USize => curried = Ty::USize, Token::ISize => curried = Ty::ISize, Token::F64 => curried = Ty::F64, Token::U8 => curried = Ty::U8, Token::Char => curried = Ty::Char, - _ => panic!("type lang issue, unmatched value type"), + _ => panic!("type lang issue, unmatched value type: {:?}", _vt.val), }; let copied = curried.clone(); let full = tree!(ValueType, copied); diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 29290b5..2ac90fc 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -523,7 +523,7 @@ impl<'s> Parser<'s> { .collect_if(Token::OBrace) .xexpect_token(&self, "expected '{'".to_string())?; let mut exprs: Vec> = vec![]; - loop { + 'l: loop { match self.inner_decl()? { Some(x) => exprs.push(x), None => match self.reassign()? { @@ -534,7 +534,10 @@ impl<'s> Parser<'s> { Some(x) => exprs.push(x), None => match self._while()? { Some(x) => exprs.push(x), - None => break, + None => match self._match()? { + Some(x) => exprs.push(x), + None => break 'l, + }, }, }, }, @@ -601,14 +604,8 @@ impl<'s> Parser<'s> { "expected at least 2 match arms ' => ( | | )'".to_string(), )?; arms.push(second_arm); - loop { - match self.arm() { - Ok(Some(x)) => arms.push(x), - Ok(None) => break, - Err(e) => { - return Err(e); - } - } + while let Some(a) = self.arm()? { + arms.push(a); } let _ = self .lexer @@ -648,7 +645,7 @@ impl<'s> Parser<'s> { pub fn or(&mut self) -> ResultExpr { self.and().xresult_or(|mut left| { - while let Some(bin) = self.lexer.collect_if(Token::Bar) { + while let Some(bin) = self.lexer.collect_if(Token::OrLog) { left = self .and() .xresult_or(|right| result_expr!(BinOp, left, bin, right))? @@ -658,7 +655,7 @@ impl<'s> Parser<'s> { } pub fn and(&mut self) -> ResultExpr { self.equality().xresult_or(|mut left| { - while let Some(bin) = self.lexer.collect_if(Token::Ampersand) { + while let Some(bin) = self.lexer.collect_if(Token::AndLog) { left = self .equality() .xresult_or(|right| result_expr!(BinOp, left, bin, right))? diff --git a/token/src/lib.rs b/token/src/lib.rs index d0dfd66..9e785b6 100644 --- a/token/src/lib.rs +++ b/token/src/lib.rs @@ -267,9 +267,9 @@ pub enum Token { #[token("&=")] AndAs, - #[regex(r#"'([^'\\]|\\t|\\u|\\n|\\')*'"#)] - #[regex(r#"`([^`\\]|\\t|\\u|\\n|\\`)*`"#)] - #[regex(r#""([^"\\]|\\t|\\u|\\n|\\")*""#)] + #[regex(r#"["]([^"\\\n]|\\.|\\\n)*["]"#)] + #[regex(r#"[']([^'\\\n]|\\.|\\\n)*[']"#)] + #[regex(r#"[`]([^`\\\n]|\\.|\\\n)*[`]"#)] Chars, #[regex("[1-9][0-9]*\\.[0-9]+|0\\.[0-9]+|0|[1-9][0-9]*")] @@ -358,5 +358,9 @@ mod tests { fn it_tokenizes_chars() { let mut lexer1 = Token::lexer(r#""hello""#); assert_eq!(lexer1.next(), Some(Ok(Token::Chars))); + let mut lexer2 = Token::lexer(r#"'\\'"#); + assert_eq!(lexer2.next(), Some(Ok(Token::Chars))); + let mut lexer3 = Token::lexer(r#"'unterminated string"#); + assert_eq!(lexer3.next(), Some(Err(()))); } } From 95edba27b70befc69d31299c8b097956e85d5b9d Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 25 Dec 2024 20:41:20 -0600 Subject: [PATCH 2/3] lint while next --- bootstrap/src/token.ty | 127 ++++++++++++++++++++--------------------- linter/src/lib.rs | 16 ++++++ types/src/lib.rs | 3 + 3 files changed, 82 insertions(+), 64 deletions(-) diff --git a/bootstrap/src/token.ty b/bootstrap/src/token.ty index b9be4b9..c9e4a6d 100644 --- a/bootstrap/src/token.ty +++ b/bootstrap/src/token.ty @@ -223,6 +223,69 @@ const keywords: [[char]] = [ "catch" ] +const word_len_check = fn(buf: &[char]) u32 { + let len = 0 + while (buf.len != len) { + const c = buf[len] + match (c) { + c.isAlphaNumeric() => { len += 1 } + (c == '_' || c == '-') => { len += 1 } + _ => { break } + } + } + return len +} + +const tokenize_chars = fn(buf: &[char], len: *u32) Token { + let token = Token.Symbol + len = word_len_check(buf) + const check = buf[0..len] + for (keywords) fn(word: [char], idx: u32) void { + if (word.len == len) { + if (word == check) { + token = idx as Token + break + } + } + } + return token +} + +const skip_whitespace = fn(buf: &[char]) u32 { + let len = 0 + while (buf.len != len) { + const c = buf[len] + match (c) { + c == ' ' || c == '\t' || c == '\r' => { len += 1 } + _ => { break } + } + } + return len +} + +const build_string = fn(buf: &[char], len: *u32, end: char) TokenError!Token { + len = 1 + while (buf.len != len) { + const c = buf[len] + match (c) { + c == '\\' => { + len += 1 + if (buf.len == len + 1) { + return TokenError.UnexpectedEnd + } + } + c == end => { + len += 1 + break + } + _ => { len += 1 } + } + } + if (len == 1) { + return TokenError.UnexpectedEnd + } + return Token.String +} pub const get_next = fn(buf: &[char], len: *u32) TokenError!Token { len = 0 const c = buf[0] @@ -399,67 +462,3 @@ pub const get_next = fn(buf: &[char], len: *u32) TokenError!Token { } } } - -const tokenize_chars = fn(buf: &[char], len: *u32) Token { - let token = Token.Symbol - len = word_len_check(buf) - const check = buf[0..len] - for (keywords) fn(word: [char], idx: u32) void { - if (word.len == len) { - if (word == check) { - token = idx as Token - break - } - } - } - return token -} - -const word_len_check = fn(buf: &[char]) u32 { - let len = 0 - while (buf.len != len) { - const c = buf[len] - match (c) { - c.isAlphaNumeric() => { len += 1 } - (c == '_' || c == '-') => { len += 1 } - _ => { break } - } - } - return len -} - -const skip_whitespace = fn(buf: &[char]) u32 { - let len = 0 - while (buf.len != len) { - const c = buf[len] - match (c) { - c == ' ' || c == '\t' || c == '\r' => { len += 1 } - _ => { break } - } - } - return len -} - -const build_string = fn(buf: &[char], len: *u32, end: char) TokenError!Token { - len = 1 - while (buf.len != len) { - const c = buf[len] - match (c) { - c == '\\' => { - len += 1 - if (buf.len == len + 1) { - return TokenError.UnexpectedEnd - } - } - c == end => { - len += 1 - break - } - _ => { len += 1 } - } - } - if (len == 1) { - return TokenError.UnexpectedEnd - } - return Token.String -} diff --git a/linter/src/lib.rs b/linter/src/lib.rs index b38a9ef..0ddfe80 100644 --- a/linter/src/lib.rs +++ b/linter/src/lib.rs @@ -105,6 +105,7 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { Expr::RetOp(ret) => self.check_ret_op(&ret), Expr::ArgDef(arg) => self.check_arg_def(&arg), Expr::ArrayType(arr) => self.check_array_type(&arr), + Expr::ArrayAccess(arr) => self.check_array_access(&arr), _ => panic!("type-lang linter issue, expr not implemented {:?}", to_cmp), } } @@ -245,6 +246,7 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { pub fn check_symbol_ref(&mut self, symbol: &Symbol) -> ResultTreeType { let ss = self.scopes.get(self.curr_scope as usize).unwrap(); + println!("symbol = {:?}", symbol); let tt = ss .get_tt_same_up(&symbol.val.slice, self.ttbls, self.scopes) .unwrap(); @@ -763,6 +765,20 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { return ok_tree!(Return, unop, curried); } + pub fn check_array_access(&mut self, arr: &ast::ArrayAccess) -> ResultTreeType { + let prev = self.lint_recurse(&arr.prev)?; + let inner = self.lint_recurse(&arr.inner)?; + let curried = prev.1.clone(); + let arrtype = types::ArrayAccess { + prev: prev.0, + inner: inner.0, + curried: prev.1, + }; + let full: Rc> = tree!(ArrayAccess, arrtype); + + return Ok((full, curried)); + } + pub fn check_array_type(&mut self, arr: &ArrayType) -> ResultTreeType { let result = self.lint_recurse(&arr.arr_of)?; let curried = result.1.clone(); diff --git a/types/src/lib.rs b/types/src/lib.rs index 4f074ca..16f7934 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -234,6 +234,7 @@ pub enum TypeTree { Not(UnaryOp), // values PropAccess(PropAccess), + ArrayAccess(ArrayAccess), SymbolAccess(SymbolAccess), RestAccess(NoOp), SelfAccess(NoOp), @@ -316,6 +317,7 @@ impl TypeTree { TypeTree::Negate(x) => x.curried.clone(), TypeTree::Not(x) => x.curried.clone(), TypeTree::PropAccess(x) => x.curried.clone(), + TypeTree::ArrayAccess(x) => x.curried.clone(), TypeTree::SymbolAccess(x) => x.curried.clone(), TypeTree::RestAccess(x) => x.curried.clone(), TypeTree::SelfAccess(x) => x.curried.clone(), @@ -435,6 +437,7 @@ impl TypeTree { TypeTree::Negate(_) => "negation", TypeTree::Not(_) => "boolean negatation", TypeTree::PropAccess(_) => "property access", + TypeTree::ArrayAccess(_) => "array index access", TypeTree::SymbolAccess(_) => "symbol reference", TypeTree::RestAccess(_) => "rest access", TypeTree::SelfAccess(_) => "self reference", From 62a6ff40ff5202ab78ddc3c6fdd5a01aa339909c Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 26 Dec 2024 11:23:31 -0600 Subject: [PATCH 3/3] linting through token.ty is complete, shortcuts taken --- bootstrap/src/token.ty | 16 ++++++++ linter/src/lib.rs | 92 ++++++++++++++++++++++++++++++++++++++++-- types/src/lib.rs | 31 ++++++++++---- 3 files changed, 128 insertions(+), 11 deletions(-) diff --git a/bootstrap/src/token.ty b/bootstrap/src/token.ty index c9e4a6d..4115518 100644 --- a/bootstrap/src/token.ty +++ b/bootstrap/src/token.ty @@ -236,6 +236,22 @@ const word_len_check = fn(buf: &[char]) u32 { return len } +// todo:: make this tokenize numbers +const tokenize_num = fn(buf: &[char], len: *u32) Token { + let token = Token.Symbol + len = word_len_check(buf) + const check = buf[0..len] + for (keywords) fn(word: [char], idx: u32) void { + if (word.len == len) { + if (word == check) { + token = idx as Token + break + } + } + } + return token +} + const tokenize_chars = fn(buf: &[char], len: *u32) Token { let token = Token.Symbol len = word_len_check(buf) diff --git a/linter/src/lib.rs b/linter/src/lib.rs index 0ddfe80..c78a7b1 100644 --- a/linter/src/lib.rs +++ b/linter/src/lib.rs @@ -73,6 +73,7 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { Expr::Arm(arm) => self.check_arm(&arm), Expr::Rest(_) => self.check_rest(), Expr::UndefinedValue(_) => self.check_undefined(), + Expr::While(wh) => self.check_while(wh), Expr::UnOp(un) => match un.op.token { Token::Dash => self.check_negate(un), Token::Exclam => self.check_not(un), @@ -87,6 +88,11 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { Token::Dash => self.check_minus(&bin), Token::Equality => self.check_equality(&bin), Token::Asterisk => self.check_mul(&bin), + Token::NotEquality => self.check_not_eq(&bin), + Token::OrLog => self.check_or_log(&bin), + Token::Range => self.check_range(&bin), + Token::CastAs => self.check_cast(&bin), + Token::Gt => self.check_gt(&bin), _ => panic!( "type-lang linter issue, binary op not implemented {:?}", bin @@ -158,8 +164,13 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { }); // todo:: get the last one if ret, curry, if not void - let curried = blk.exprs.last().unwrap().get_curried().clone(); - ok_tree!(Block, blk, curried) + let last = blk.exprs.last(); + if let Some(l) = last { + let curried = l.get_curried().clone(); + return ok_tree!(Block, blk, curried); + } + let curried = Ty::Void; + return ok_tree!(Block, blk, curried); } pub fn check_undefined(&mut self) -> ResultTreeType { @@ -246,7 +257,6 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { pub fn check_symbol_ref(&mut self, symbol: &Symbol) -> ResultTreeType { let ss = self.scopes.get(self.curr_scope as usize).unwrap(); - println!("symbol = {:?}", symbol); let tt = ss .get_tt_same_up(&symbol.val.slice, self.ttbls, self.scopes) .unwrap(); @@ -826,6 +836,66 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { } } + pub fn check_gt(&mut self, bin: &BinOp) -> ResultTreeType { + let left = self.lint_recurse(&bin.left)?; + let right = self.lint_recurse(&bin.right)?; + let binop = BinaryOp { + left: left.0, + right: right.0, + curried: Ty::Bool, + }; + let curried = binop.curried.clone(); + return ok_tree!(Gt, binop, curried); + } + + pub fn check_cast(&mut self, bin: &BinOp) -> ResultTreeType { + let left = self.lint_recurse(&bin.left)?; + let right = self.lint_recurse(&bin.right)?; + let binop = BinaryOp { + left: left.0, + right: right.0, + curried: Ty::Bool, + }; + let curried = binop.curried.clone(); + return ok_tree!(CastAs, binop, curried); + } + + pub fn check_range(&mut self, bin: &BinOp) -> ResultTreeType { + let left = self.lint_recurse(&bin.left)?; + let right = self.lint_recurse(&bin.right)?; + let binop = BinaryOp { + left: left.0, + right: right.0, + curried: Ty::Bool, + }; + let curried = binop.curried.clone(); + return ok_tree!(Range, binop, curried); + } + + pub fn check_or_log(&mut self, bin: &BinOp) -> ResultTreeType { + let left = self.lint_recurse(&bin.left)?; + let right = self.lint_recurse(&bin.right)?; + let binop = BinaryOp { + left: left.0, + right: right.0, + curried: Ty::Bool, + }; + let curried = binop.curried.clone(); + return ok_tree!(OrLog, binop, curried); + } + + pub fn check_not_eq(&mut self, bin: &BinOp) -> ResultTreeType { + let left = self.lint_recurse(&bin.left)?; + let right = self.lint_recurse(&bin.right)?; + let binop = BinaryOp { + left: left.0, + right: right.0, + curried: Ty::Bool, + }; + let curried = binop.curried.clone(); + return ok_tree!(NotEq, binop, curried); + } + pub fn check_not(&mut self, un: &UnOp) -> ResultTreeType { let result = self.lint_recurse(&un.val)?; let mut unop = UnaryOp { @@ -899,7 +969,7 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { }; let curried = binop.curried.clone(); - ok_tree!(Plus, binop, curried) + ok_tree!(Eq, binop, curried) } pub fn check_minus(&mut self, bin: &BinOp) -> ResultTreeType { @@ -948,6 +1018,20 @@ impl<'buf, 'ttb, 'sco> LintSource<'buf, 'ttb, 'sco> { return ok_tree!(Arm, binop, curried); } + pub fn check_while(&mut self, wh: &While) -> ResultTreeType { + let expr = self.lint_recurse(&wh.expr)?; + let var = self.lint_recurse(&wh.var_loop)?; + let while_op = WhileOp { + expr: expr.0, + expr_curried: expr.1, + var_loop: var.0, + var_curried: var.1, + }; + let curried = while_op.var_curried.clone(); + + return ok_tree!(While, while_op, curried); + } + pub fn check_borrow_mut(&mut self, un: &UnOp) -> ResultTreeType { let result = self.lint_recurse(&un.val)?; let mut unop = UnaryOp { diff --git a/types/src/lib.rs b/types/src/lib.rs index 16f7934..b0cf2a0 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -1,12 +1,6 @@ use core::fmt; use std::rc::Rc; -#[derive(Debug)] -pub struct FileContainer { - pub top_items: Vec>>, - pub curried: Vec, -} - #[derive(Debug)] pub struct SigTypes { pub left: Ty, @@ -83,6 +77,14 @@ pub struct ForOp { pub body_curried: Ty, } +#[derive(Debug)] +pub struct WhileOp { + pub expr: Rc>, + pub expr_curried: Ty, + pub var_loop: Rc>, + pub var_curried: Ty, +} + #[derive(Debug)] pub struct IfOp { pub in_expr: Rc>, @@ -209,6 +211,7 @@ pub enum TypeTree { Invoke(Invoke), Match(MatchOp), Arm(BinaryOp), + While(WhileOp), Block(Block), Return(UnaryOp), ReturnVoid(NoOp), @@ -217,12 +220,16 @@ pub enum TypeTree { BreakVoid(NoOp), // binops Plus(BinaryOp), + NotEq(BinaryOp), + Eq(BinaryOp), + OrLog(BinaryOp), Minus(BinaryOp), Divide(BinaryOp), Multiply(BinaryOp), Modulo(BinaryOp), Range(BinaryOp), CastAs(BinaryOp), + Gt(BinaryOp), BubbleUndef(BinaryOp), BubbleError(BinaryOp), // unops @@ -291,6 +298,7 @@ impl TypeTree { TypeTree::SigTypes(x) => x.left.clone(), TypeTree::ErrorInfo(x) => x.curried.clone(), TypeTree::For(x) => x.body_curried.clone(), + TypeTree::While(x) => x.var_curried.clone(), TypeTree::If(x) => x.body_curried.clone(), TypeTree::Invoke(x) => x.curried.clone(), TypeTree::Match(x) => x.curried_arms.clone(), @@ -357,6 +365,10 @@ impl TypeTree { TypeTree::ValueType(x) => x.clone(), TypeTree::SingleType(x) => x.clone(), TypeTree::ArrayType(x) => x.curried.clone(), + TypeTree::NotEq(x) => x.curried.clone(), + TypeTree::Eq(x) => x.curried.clone(), + TypeTree::OrLog(x) => x.curried.clone(), + TypeTree::Gt(x) => x.curried.clone(), } } pub fn into_declarator(&self) -> &DeclaratorInfo { @@ -411,6 +423,7 @@ impl TypeTree { TypeTree::SigTypes(_) => "type signature", TypeTree::ErrorInfo(_) => "error declaration", TypeTree::For(_) => "for loop", + TypeTree::While(_) => "while loop", TypeTree::If(_) => "if statement", TypeTree::Invoke(_) => "function invocation", TypeTree::Match(_) => "match", @@ -429,7 +442,7 @@ impl TypeTree { TypeTree::Range(_) => "range", TypeTree::CastAs(_) => "cast", TypeTree::BubbleUndef(_) => "undefinded bubble", - TypeTree::BubbleError(_) => "error bubble", + TypeTree::BubbleError(_) => "try error bubble", TypeTree::ReadBorrow(_) => "read borrow", TypeTree::MutBorrow(_) => "mutable borrow", TypeTree::Copy(_) => "unsized copy", @@ -477,6 +490,10 @@ impl TypeTree { TypeTree::ValueType(_) => "a value type", TypeTree::SingleType(_) => "a type", TypeTree::ArrayType(_) => "an array type", + TypeTree::NotEq(_) => "not equality check", + TypeTree::Eq(_) => "equality check", + TypeTree::OrLog(_) => "or logical check", + TypeTree::Gt(_) => "greater than logical check", } } }