diff options
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | progs/tests/simple.sy | 2 | ||||
| -rw-r--r-- | src/compiler.rs | 12 | ||||
| -rw-r--r-- | src/error.rs | 42 | ||||
| -rw-r--r-- | src/lib.rs | 10 | ||||
| -rw-r--r-- | src/main.rs | 2 | ||||
| -rw-r--r-- | src/tokenizer.rs | 5 | ||||
| -rw-r--r-- | sylt_macro/src/lib.rs | 78 |
8 files changed, 150 insertions, 22 deletions
@@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Edvard Thörnros & Gustav Sörnäs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/progs/tests/simple.sy b/progs/tests/simple.sy index 84bc86d..e36d2bf 100644 --- a/progs/tests/simple.sy +++ b/progs/tests/simple.sy @@ -20,4 +20,4 @@ qq :: fn { // Steg 1: Hitta sektioner -// Dela sektioner, compilera felera sektioner efter varandra +// Dela sektioner, compilera felera sektioner efter varandra
\ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index aa491e6..2244198 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -543,6 +543,18 @@ impl<'a> Compiler<'a> { fn eat(&mut self) -> Token { let t = self.peek(); self.curr += 1; + match t { + Token::GitConflictBegin => { + self.curr -= 1; + let start = self.line(); + self.curr += 1; + while !matches!(self.eat(), Token::GitConflictEnd) {} + self.panic = false; + self.error_on_line(ErrorKind::GitConflictError(start, self.line()), start, None); + self.panic = true; + } + _ => {} + } t } diff --git a/src/error.rs b/src/error.rs index c2ad228..9aca985 100644 --- a/src/error.rs +++ b/src/error.rs @@ -32,6 +32,8 @@ pub enum ErrorKind { /// (line, token) SyntaxError(usize, Token), + /// (start, end) + GitConflictError(usize, usize), } #[derive(Debug, Clone)] @@ -67,9 +69,8 @@ impl fmt::Display for ErrorKind { write!(f, "Argument types do not match, expected [{:?}] but got [{:?}]", expected, given) } - ErrorKind::IndexOutOfBounds(value, len, slot) => { - write!(f, "Failed to index for {:?} - length is {} but index is {}", - value, len, slot) + ErrorKind::IndexError(value, slot) => { + write!(f, "Cannot index value '{:?}' with type '{:?}'.", value, slot) } ErrorKind::ExternTypeMismatch(name, types) => { write!(f, "Extern function '{}' doesn't accept argument(s) with type(s) {:?}", @@ -81,27 +82,32 @@ impl fmt::Display for ErrorKind { .fold(String::new(), |a, v| { format!("{}{:?}, ", a, v) }); write!(f, "Cannot apply {:?} to values {}", op, values) } - ErrorKind::AssertFailed => { - write!(f, "Assertion failed") + ErrorKind::UnknownField(obj, field) => { + write!(f, "Cannot find field '{}' on {:?}", field, obj) } - ErrorKind::SyntaxError(line, token) => { - write!(f, "Syntax Error on line {} at token {:?}", line, token) + ErrorKind::ArgumentCount(expected, given) => { + write!(f, "Incorrect argument count, expected {} but got {}.", + expected, given) } - ErrorKind::Unreachable => { - write!(f, "Reached unreachable code.") + ErrorKind::IndexOutOfBounds(value, len, slot) => { + write!(f, "Failed to index for {:?} - length is {} but index is {}", + value, len, slot) + } + ErrorKind::AssertFailed => { + write!(f, "Assertion failed") } ErrorKind::InvalidProgram => { write!(f, "{}", "[!!] Invalid program [!!]".bold()) } - ErrorKind::IndexError(value, slot) => { - write!(f, "Cannot index value '{:?}' with type '{:?}'.", value, slot) + ErrorKind::Unreachable => { + write!(f, "Reached unreachable code.") } - ErrorKind::UnknownField(obj, field) => { - write!(f, "Cannot find field '{}' on {:?}", field, obj) + ErrorKind::SyntaxError(line, token) => { + write!(f, "Syntax Error on line {} at token {:?}", line, token) } - ErrorKind::ArgumentCount(expected, given) => { - write!(f, "Incorrect argument count, expected {} but got {}.", - expected, given) + ErrorKind::GitConflictError(start_line, end_line) => { + write!(f, "Git conflict markers found between lines {} and {}", + start_line, end_line) } } } @@ -109,7 +115,7 @@ impl fmt::Display for ErrorKind { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let prompt = "*****".red(); + let prompt = " "; let message = match &self.message { Some(s) => format!("\n{} {}", prompt, s), None => String::from(""), @@ -123,7 +129,7 @@ impl fmt::Display for Error { String::new() }; - write!(f, "\n {} {}:{} \n{} {}{}{}\n", "ERR".red(), + write!(f, "{} {}:{}\n{} {}{}{}", "ERROR".red(), self.file.display().blue(), self.line.blue(), prompt, self.kind, message, line) } } @@ -1369,4 +1369,14 @@ q <=> 3 ); + test_string!(conflict_markers, " +<<<<<<< HEAD +print extern_test(4.0) +======= +print extern_test(5.0) +>>>>>>> 2 +", + [ErrorKind::SyntaxError(_, _), ErrorKind::GitConflictError(2, 6)] + ); + } diff --git a/src/main.rs b/src/main.rs index bc68d40..28e4e79 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ struct Args { fn main() { let args = parse_args(); let file = args.file.unwrap_or_else(|| Path::new("progs/tests/simple.sy").to_owned()); - let errs = match run_file(&file, args.print, vec![(String::from("extern_test"), extern_test)]) { + let errs = match run_file(&file, args.print, sylt_macro::link!(extern_test as test)) { Err(it) => it, _ => return, }; diff --git a/src/tokenizer.rs b/src/tokenizer.rs index b54e194..2c8e5e8 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -127,6 +127,11 @@ pub enum Token { #[token("\n")] Newline, + #[token("<<<<<<<")] + GitConflictBegin, + #[token(">>>>>>>")] + GitConflictEnd, + #[regex(r"//[^\n]*", logos::skip)] Comment, diff --git a/sylt_macro/src/lib.rs b/sylt_macro/src/lib.rs index fc43b5c..3b8b37c 100644 --- a/sylt_macro/src/lib.rs +++ b/sylt_macro/src/lib.rs @@ -73,15 +73,89 @@ pub fn extern_function(tokens: TokenStream) -> TokenStream { #[allow(unused_variables)] match __values { #(#typecheck_blocks),* - _ => Err(sylt::error::ErrorKind::ExternTypeMismatch(stringify!(#function).to_string(), __values.iter().map(|v| sylt::Type::from(v)).collect())) + _ => Err(sylt::error::ErrorKind::ExternTypeMismatch( + stringify!(#function).to_string(), + __values.iter().map(|v| sylt::Type::from(v)).collect() + )) } } else { match __values { #(#eval_blocks),* - _ => Err(sylt::error::ErrorKind::ExternTypeMismatch(stringify!(#function).to_string(), __values.iter().map(|v| sylt::Type::from(v)).collect())) + _ => Err(sylt::error::ErrorKind::ExternTypeMismatch( + stringify!(#function).to_string(), + __values.iter().map(|v| sylt::Type::from(v)).collect() + )) } } } }; TokenStream::from(tokens) } + +struct LinkRename { + _as: Token![as], + name: syn::Ident, +} + +impl Parse for LinkRename { + fn parse(input: ParseStream) -> Result<Self> { + Ok(Self { + _as: input.parse()?, + name: input.parse()?, + }) + } +} + +struct Link { + path: syn::Path, + rename: Option<LinkRename>, +} + +impl Parse for Link { + fn parse(input: ParseStream) -> Result<Self> { + Ok(Self { + path: input.parse()?, + rename: input.parse().ok(), + }) + } +} + +struct Links { + links: Vec<Link>, +} + +impl Parse for Links { + fn parse(input: ParseStream) -> Result<Self> { + let mut res = Self { + links: Vec::new(), + }; + while !input.is_empty() { + res.links.push(input.parse()?); + let _comma: Option<Token![,]> = input.parse().ok(); + } + Ok(res) + } +} + + +#[proc_macro] +pub fn link(tokens: TokenStream) -> TokenStream { + let links: Links = parse_macro_input!(tokens); + + let links: Vec<_> = links.links.iter().map(|link| { + let name = if let Some(rename) = &link.rename { + &rename.name + } else { + &link.path.segments.last().unwrap().ident + }; + let path = &link.path; + quote! { + (stringify!(#name).to_string(), #path) + } + }).collect(); + + let tokens = quote! { + vec![ #(#links),* ] + }; + TokenStream::from(tokens) +} |
