Merge branch 'main' into beta

This commit is contained in:
Shunsuke Shibayama 2022-09-19 10:45:09 +09:00
commit a9d4e5982b
8 changed files with 107 additions and 19 deletions

View file

@ -135,4 +135,4 @@
* [ ] Write educational materials to learn Erg while creating applications (e.g. CLI chess game -> GUI chess game, calculator -> toy language) * [ ] 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 Dyne (CPython compatible VM)
* [ ] Develop Kayser (WebAssembly backend) * [ ] Develop Kayser (WebAssembly backend)
* [ ] Develop Barye (LLVM backend) * [ ] Develop Gal (LLVM backend)

View file

@ -1330,13 +1330,13 @@ impl Context {
proc.register_superclass(Obj, &obj); proc.register_superclass(Obj, &obj);
// TODO: lambda // TODO: lambda
proc.register_marker_trait(mono("Named")); proc.register_marker_trait(mono("Named"));
let mut func = Self::mono_class("Function", Self::TOP_LEVEL); let mut func = Self::mono_class("Func", Self::TOP_LEVEL);
func.register_superclass(mono("Procedure"), &proc); func.register_superclass(mono("Proc"), &proc);
func.register_superclass(Obj, &obj); func.register_superclass(Obj, &obj);
// TODO: lambda // TODO: lambda
func.register_marker_trait(mono("Named")); func.register_marker_trait(mono("Named"));
let mut qfunc = Self::mono_class("QuantifiedFunction", Self::TOP_LEVEL); let mut qfunc = Self::mono_class("QuantifiedFunc", Self::TOP_LEVEL);
qfunc.register_superclass(mono("Function"), &func); qfunc.register_superclass(mono("Func"), &func);
qfunc.register_superclass(Obj, &obj); qfunc.register_superclass(Obj, &obj);
self.register_builtin_type(Obj, obj, Const); self.register_builtin_type(Obj, obj, Const);
// self.register_type(mono("Record"), vec![], record, 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(array_mut_t, array_mut_, Const);
self.register_builtin_type(range_t, range, Const); self.register_builtin_type(range_t, range, Const);
self.register_builtin_type(mono("Tuple"), tuple_, Const); self.register_builtin_type(mono("Tuple"), tuple_, Const);
self.register_builtin_type(mono("Procedure"), proc, Const); self.register_builtin_type(mono("Proc"), proc, Const);
self.register_builtin_type(mono("Function"), func, Const); self.register_builtin_type(mono("Func"), func, Const);
self.register_builtin_type(mono("QuantifiedFunction"), qfunc, Const); self.register_builtin_type(mono("QuantifiedFunc"), qfunc, Const);
} }
fn init_builtin_funcs(&mut self) { fn init_builtin_funcs(&mut self) {

View file

@ -1089,13 +1089,13 @@ impl Context {
} }
} }
Type::Quantified(_) => { 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); return Some(res);
} }
} }
Type::Subr(_subr) => match _subr.kind { Type::Subr(_subr) => match _subr.kind {
SubrKind::Func => { 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); return Some(res);
} }
} }
@ -1157,7 +1157,7 @@ impl Context {
} }
} }
Type::Quantified(_) => { 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); return Some(res);
} }
} }

View file

@ -285,6 +285,62 @@ impl Lexer /*<'a>*/ {
Ok(()) 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<LexResult<Token>> { fn lex_space_indent_dedent(&mut self) -> Option<LexResult<Token>> {
let is_toplevel = self.cursor > 0 let is_toplevel = self.cursor > 0
&& !self.indent_stack.is_empty() && !self.indent_stack.is_empty()
@ -349,6 +405,11 @@ impl Lexer /*<'a>*/ {
} }
// ignore indents if the current line is a comment // ignore indents if the current line is a comment
if let Some('#') = self.peek_cur_ch() { 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() { if let Err(e) = self.lex_comment() {
return Some(Err(e)); return Some(Err(e));
} }
@ -562,6 +623,7 @@ impl Lexer /*<'a>*/ {
'r' => s.push('\r'), 'r' => s.push('\r'),
'n' => s.push('\n'), 'n' => s.push('\n'),
'\'' => s.push('\''), '\'' => s.push('\''),
'"' => s.push('"'),
't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace 't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace
'\\' => s.push('\\'), '\\' => s.push('\\'),
_ => { _ => {
@ -630,6 +692,11 @@ impl Iterator for Lexer /*<'a>*/ {
return indent_dedent; return indent_dedent;
} }
if let Some('#') = self.peek_cur_ch() { 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() { if let Err(e) = self.lex_comment() {
return Some(Err(e)); return Some(Err(e));
} }

View file

@ -0,0 +1,7 @@
#[
aa
#[ aa ]#
aa
]#
a = 1

View file

@ -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 = 1_234 + 1113.* 3_000.2e-4 ** 0003 * .4
a, _, ...b = five_elem_tuple a, _, ...b = five_elem_tuple
f x, y = f x, y =
x + y x + y
if! True, do!: if! True, do!:
print! "\\hello, world\"" print! "\"\\hello, world\\\""
#[
indented comment
dedented comment
]#
10.times! do!: 10.times! do!:
if! x.y.z, do!: if! x.y.z, do!:
print! "" print! ""

View file

@ -9,7 +9,7 @@
0.00, -0.0, .1, 400. 0.00, -0.0, .1, 400.
# Str Literal # Str Literal
"", "a", "こんにちは", "\" \\ " "", "a", "こんにちは", "\"\\", "\"\'\\\0\r\n\t"
# Boolean Litteral # Boolean Litteral
True, False True, False

View file

@ -18,7 +18,6 @@ fn test_lexer_for_basic() -> ParseResult<()> {
let mut lexer = Lexer::new(Input::File(FILE1.into())); let mut lexer = Lexer::new(Input::File(FILE1.into()));
let newline = "\n"; let newline = "\n";
let /*mut*/ token_array = vec![ let /*mut*/ token_array = vec![
(Newline, newline),
(Newline, newline), (Newline, newline),
(Newline, newline), (Newline, newline),
(Symbol, "_a"), (Symbol, "_a"),
@ -37,7 +36,7 @@ fn test_lexer_for_basic() -> ParseResult<()> {
(Comma, ","), (Comma, ","),
(UBar, "_"), (UBar, "_"),
(Comma, ","), (Comma, ","),
(Spread, "..."), // EllipsisLit (EllipsisLit, "..."),
(Symbol, "b"), (Symbol, "b"),
(Equal, "="), (Equal, "="),
(Symbol, "five_elem_tuple"), (Symbol, "five_elem_tuple"),
@ -62,7 +61,8 @@ fn test_lexer_for_basic() -> ParseResult<()> {
(Newline, newline), (Newline, newline),
(Indent, " "), (Indent, " "),
(Symbol, "print!"), (Symbol, "print!"),
(StrLit, "\"\\\\hello, world\\\"\""), (StrLit, "\"\"\\hello, world\\\"\""),
(Newline, newline),
(Newline, newline), (Newline, newline),
(NatLit, "10"), (NatLit, "10"),
(Dot, "."), (Dot, "."),
@ -264,7 +264,9 @@ fn test_lexer_for_literals() -> ParseResult<()> {
(Comma, ","), (Comma, ","),
(StrLit, "\"こんにちは\""), (StrLit, "\"こんにちは\""),
(Comma, ","), (Comma, ","),
(StrLit, "\"\\\" \\\\ \""), (StrLit, "\"\"\\\""),
(Comma, ","),
(StrLit, "\"\"\'\\\0\r\n \""),
(Newline, newline), (Newline, newline),
(Newline, newline), (Newline, newline),
(Newline, newline), (Newline, newline),