diff --git a/TODO.md b/TODO.md index bf5622d1..cb82dc28 100644 --- a/TODO.md +++ b/TODO.md @@ -135,4 +135,4 @@ * [ ] Write educational materials to learn Erg while creating applications (e.g. CLI chess game -> GUI chess game, calculator -> toy language) * [ ] Develop Dyne (CPython compatible VM) * [ ] Develop Kayser (WebAssembly backend) -* [ ] Develop Barye (LLVM backend) +* [ ] Develop Gal (LLVM backend) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index bcf525df..35d607d0 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -1330,13 +1330,13 @@ impl Context { proc.register_superclass(Obj, &obj); // TODO: lambda proc.register_marker_trait(mono("Named")); - let mut func = Self::mono_class("Function", Self::TOP_LEVEL); - func.register_superclass(mono("Procedure"), &proc); + let mut func = Self::mono_class("Func", Self::TOP_LEVEL); + func.register_superclass(mono("Proc"), &proc); func.register_superclass(Obj, &obj); // TODO: lambda func.register_marker_trait(mono("Named")); - let mut qfunc = Self::mono_class("QuantifiedFunction", Self::TOP_LEVEL); - qfunc.register_superclass(mono("Function"), &func); + let mut qfunc = Self::mono_class("QuantifiedFunc", Self::TOP_LEVEL); + qfunc.register_superclass(mono("Func"), &func); qfunc.register_superclass(Obj, &obj); self.register_builtin_type(Obj, obj, Const); // self.register_type(mono("Record"), vec![], record, Const); @@ -1423,9 +1423,9 @@ impl Context { self.register_builtin_type(array_mut_t, array_mut_, Const); self.register_builtin_type(range_t, range, Const); self.register_builtin_type(mono("Tuple"), tuple_, Const); - self.register_builtin_type(mono("Procedure"), proc, Const); - self.register_builtin_type(mono("Function"), func, Const); - self.register_builtin_type(mono("QuantifiedFunction"), qfunc, Const); + self.register_builtin_type(mono("Proc"), proc, Const); + self.register_builtin_type(mono("Func"), func, Const); + self.register_builtin_type(mono("QuantifiedFunc"), qfunc, Const); } fn init_builtin_funcs(&mut self) { diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index fb0b63e8..e78a42e0 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1089,13 +1089,13 @@ impl Context { } } Type::Quantified(_) => { - if let Some(res) = self.get_nominal_type_ctx(&mono("QuantifiedFunction")) { + if let Some(res) = self.get_nominal_type_ctx(&mono("QuantifiedFunc")) { return Some(res); } } Type::Subr(_subr) => match _subr.kind { SubrKind::Func => { - if let Some(res) = self.get_nominal_type_ctx(&mono("Function")) { + if let Some(res) = self.get_nominal_type_ctx(&mono("Func")) { return Some(res); } } @@ -1157,7 +1157,7 @@ impl Context { } } Type::Quantified(_) => { - if let Some(res) = self.get_mut_nominal_type_ctx(&mono("QuantifiedFunction")) { + if let Some(res) = self.get_mut_nominal_type_ctx(&mono("QuantifiedFunc")) { return Some(res); } } diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index f7196e1c..cd1631d5 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -285,6 +285,62 @@ impl Lexer /*<'a>*/ { Ok(()) } + fn lex_multi_line_comment(&mut self) -> LexResult<()> { + let mut s = "".to_string(); + let mut nest_level = 0; + loop { + match self.peek_cur_ch() { + Some(c) => { + if let Some(next_c) = self.peek_next_ch() { + match (c, next_c) { + ('#', '[') => nest_level += 1, + (']', '#') => { + nest_level -= 1; + if nest_level == 0 { + return Ok(()); + } + } + _ => {} + } + if c == '\n' { + self.lineno_token_starts += 1; + self.col_token_starts = 0; + } + s.push(self.consume().unwrap()); + } + if Self::is_bidi(self.peek_cur_ch().unwrap()) { + let comment = self.emit_token(Illegal, &s); + return Err(LexError::syntax_error( + 0, + comment.loc(), + switch_lang!( + "japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています", + "simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)", + "traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)", + "english" => "invalid unicode character (bi-directional override) in comments", + ), + None, + )); + } + } + None => { + let comment = self.emit_token(Illegal, &s); + return Err(LexError::syntax_error( + 0, + comment.loc(), + switch_lang!( + "japanese" => "複数行コメントが]#で閉じられていません", + "simplified_chinese" => "未用]#号结束的多处评论", + "traditional_chinese" => "多條評論未用]#關閉", + "english" => "Multi-comment is not closed with ]#", + ), + None, + )); + } + } + } + } + fn lex_space_indent_dedent(&mut self) -> Option> { let is_toplevel = self.cursor > 0 && !self.indent_stack.is_empty() @@ -349,6 +405,11 @@ impl Lexer /*<'a>*/ { } // ignore indents if the current line is a comment if let Some('#') = self.peek_cur_ch() { + if let Some('[') = self.peek_next_ch() { + if let Err(e) = self.lex_multi_line_comment() { + return Some(Err(e)); + } + } if let Err(e) = self.lex_comment() { return Some(Err(e)); } @@ -562,6 +623,7 @@ impl Lexer /*<'a>*/ { 'r' => s.push('\r'), 'n' => s.push('\n'), '\'' => s.push('\''), + '"' => s.push('"'), 't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace '\\' => s.push('\\'), _ => { @@ -630,6 +692,11 @@ impl Iterator for Lexer /*<'a>*/ { return indent_dedent; } if let Some('#') = self.peek_cur_ch() { + if let Some('[') = self.peek_next_ch() { + if let Err(e) = self.lex_multi_line_comment() { + return Some(Err(e)); + } + } if let Err(e) = self.lex_comment() { return Some(Err(e)); } diff --git a/compiler/erg_parser/tests/comment.er b/compiler/erg_parser/tests/comment.er new file mode 100644 index 00000000..d795f412 --- /dev/null +++ b/compiler/erg_parser/tests/comment.er @@ -0,0 +1,7 @@ +#[ + aa + #[ aa ]# +aa +]# + +a = 1 diff --git a/compiler/erg_parser/tests/test1_basic_syntax.er b/compiler/erg_parser/tests/test1_basic_syntax.er index ffd77c3f..4eddb3ff 100644 --- a/compiler/erg_parser/tests/test1_basic_syntax.er +++ b/compiler/erg_parser/tests/test1_basic_syntax.er @@ -1,12 +1,24 @@ -# 基本的な構文をパーサーがパスできるかチェックする -# Check that a parser can pass the basic syntax +#[ +基本的な構文をパーサーがパスできるかチェックする +Check that a parser can pass the basic syntax + #[ + `#[`から`]#`までが複数行コメントとして扱われる + コメント内部で入れ子で複数行コメントを付けれるが、閉じ忘れに注意 + The comment from `#[` to `]#` is treated as a multi-line comment. + Nested multi-line comments can be added inside comments, but be careful not to forget to close them. + ]# +]# _a = 1_234 + 1113.* 3_000.2e-4 ** 0003 * .4 a, _, ...b = five_elem_tuple f x, y = x + y if! True, do!: - print! "\\hello, world\"" + print! "\"\\hello, world\\\"" + #[ + indented comment +dedented comment + ]# 10.times! do!: if! x.y.z, do!: print! "" diff --git a/compiler/erg_parser/tests/test3_literal_syntax.er b/compiler/erg_parser/tests/test3_literal_syntax.er index 2bbae620..d9eb12d5 100644 --- a/compiler/erg_parser/tests/test3_literal_syntax.er +++ b/compiler/erg_parser/tests/test3_literal_syntax.er @@ -9,7 +9,7 @@ 0.00, -0.0, .1, 400. # Str Literal -"", "a", "こんにちは", "\" \\ " +"", "a", "こんにちは", "\"\\", "\"\'\\\0\r\n\t" # Boolean Litteral True, False diff --git a/compiler/erg_parser/tests/tokenize_test.rs b/compiler/erg_parser/tests/tokenize_test.rs index 47744926..fca29d8b 100644 --- a/compiler/erg_parser/tests/tokenize_test.rs +++ b/compiler/erg_parser/tests/tokenize_test.rs @@ -18,7 +18,6 @@ fn test_lexer_for_basic() -> ParseResult<()> { let mut lexer = Lexer::new(Input::File(FILE1.into())); let newline = "\n"; let /*mut*/ token_array = vec![ - (Newline, newline), (Newline, newline), (Newline, newline), (Symbol, "_a"), @@ -37,7 +36,7 @@ fn test_lexer_for_basic() -> ParseResult<()> { (Comma, ","), (UBar, "_"), (Comma, ","), - (Spread, "..."), // EllipsisLit + (EllipsisLit, "..."), (Symbol, "b"), (Equal, "="), (Symbol, "five_elem_tuple"), @@ -62,7 +61,8 @@ fn test_lexer_for_basic() -> ParseResult<()> { (Newline, newline), (Indent, " "), (Symbol, "print!"), - (StrLit, "\"\\\\hello, world\\\"\""), + (StrLit, "\"\"\\hello, world\\\"\""), + (Newline, newline), (Newline, newline), (NatLit, "10"), (Dot, "."), @@ -264,7 +264,9 @@ fn test_lexer_for_literals() -> ParseResult<()> { (Comma, ","), (StrLit, "\"こんにちは\""), (Comma, ","), - (StrLit, "\"\\\" \\\\ \""), + (StrLit, "\"\"\\\""), + (Comma, ","), + (StrLit, "\"\"\'\\\0\r\n \""), (Newline, newline), (Newline, newline), (Newline, newline),