mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 20:14:45 +00:00
Fix bugs
This commit is contained in:
parent
afcf21787d
commit
ae15f95191
7 changed files with 159 additions and 57 deletions
|
@ -1522,7 +1522,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
let path = name.split("::").next().unwrap_or(name);
|
let path = name.split("::").next().unwrap_or(name);
|
||||||
let path = path.split('.').next().unwrap_or(path);
|
let path = path.split('.').next().unwrap_or(path);
|
||||||
let path = self.cfg.input.resolve(Path::new(path)).ok()?;
|
let path = self.resolve_path(Path::new(path));
|
||||||
if let Some(ctx) = self
|
if let Some(ctx) = self
|
||||||
.mod_cache
|
.mod_cache
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -1545,7 +1545,7 @@ impl Context {
|
||||||
// NOTE: This needs to be changed if we want to be able to define classes/traits outside of the top level
|
// NOTE: This needs to be changed if we want to be able to define classes/traits outside of the top level
|
||||||
let path = name.split("::").next().unwrap_or(name);
|
let path = name.split("::").next().unwrap_or(name);
|
||||||
let path = path.split('.').next().unwrap_or(path);
|
let path = path.split('.').next().unwrap_or(path);
|
||||||
let path = self.cfg.input.resolve(Path::new(path)).ok()?;
|
let path = self.resolve_path(Path::new(path));
|
||||||
if let Some(ctx) = self
|
if let Some(ctx) = self
|
||||||
.mod_cache
|
.mod_cache
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -1705,16 +1705,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
|
|
||||||
pub(crate) fn get_mod(&self, name: &str) -> Option<&Context> {
|
|
||||||
let t = self.get_var_info(name).map(|(_, vi)| vi.t.clone()).ok()?;
|
|
||||||
match t {
|
|
||||||
Type::Poly { name, mut params } if &name[..] == "Module" => {
|
|
||||||
let path =
|
|
||||||
option_enum_unwrap!(params.remove(0), TyParam::Value:(ValueObj::Str:(_)))?;
|
|
||||||
let path = Path::new(&path[..]);
|
|
||||||
// TODO: erg std
|
// TODO: erg std
|
||||||
let path = if let Ok(path) = self.cfg.input.resolve(path) {
|
pub(crate) fn resolve_path(&self, path: &Path) -> PathBuf {
|
||||||
|
if let Ok(path) = self.cfg.input.resolve(path) {
|
||||||
path
|
path
|
||||||
} else if let Ok(path) = erg_pystd_path()
|
} else if let Ok(path) = erg_pystd_path()
|
||||||
.join(format!("{}.d.er", path.display()))
|
.join(format!("{}.d.er", path.display()))
|
||||||
|
@ -1723,7 +1716,17 @@ impl Context {
|
||||||
path
|
path
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from(format!("<builtins>.{}", path.display()))
|
PathBuf::from(format!("<builtins>.{}", path.display()))
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
|
||||||
|
pub(crate) fn get_mod(&self, name: &str) -> Option<&Context> {
|
||||||
|
let t = self.get_var_info(name).map(|(_, vi)| vi.t.clone()).ok()?;
|
||||||
|
match t {
|
||||||
|
Type::Poly { name, mut params } if &name[..] == "Module" => {
|
||||||
|
let path =
|
||||||
|
option_enum_unwrap!(params.remove(0), TyParam::Value:(ValueObj::Str:(_)))?;
|
||||||
|
let path = self.resolve_path(Path::new(&path[..]));
|
||||||
self.mod_cache
|
self.mod_cache
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|cache| cache.ref_ctx(&path))
|
.and_then(|cache| cache.ref_ctx(&path))
|
||||||
|
|
|
@ -797,11 +797,11 @@ impl Context {
|
||||||
TypeSpec::PreDeclTy(predecl) => {
|
TypeSpec::PreDeclTy(predecl) => {
|
||||||
Ok(self.instantiate_predecl_t(predecl, opt_decl_t, tmp_tv_ctx)?)
|
Ok(self.instantiate_predecl_t(predecl, opt_decl_t, tmp_tv_ctx)?)
|
||||||
}
|
}
|
||||||
TypeSpec::And(lhs, rhs) => Ok(self.union(
|
TypeSpec::And(lhs, rhs) => Ok(self.intersection(
|
||||||
&self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
&self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
&self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
&self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
TypeSpec::Or(lhs, rhs) => Ok(self.intersection(
|
TypeSpec::Or(lhs, rhs) => Ok(self.union(
|
||||||
&self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
&self.instantiate_typespec(lhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
&self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
&self.instantiate_typespec(rhs, opt_decl_t, tmp_tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -1 +1,14 @@
|
||||||
.run!: (args: Str or [Str; _], shell := Bool) => NoneType
|
.CompletedProcess: ClassType
|
||||||
|
.CompletedProcess.args: Str or [Str; _]
|
||||||
|
.CompletedProcess.returncode: Int
|
||||||
|
.CompletedProcess.stdout: Bytes or NoneType
|
||||||
|
.CompletedProcess.stderr: Bytes or NoneType
|
||||||
|
|
||||||
|
.run!: (
|
||||||
|
args: Str or [Str; _],
|
||||||
|
stdin: File! or NoneType := NoneType,
|
||||||
|
stdout: File! or NoneType := NoneType,
|
||||||
|
stderr: File! or NoneType := NoneType,
|
||||||
|
capture_output := Bool,
|
||||||
|
shell := Bool,
|
||||||
|
) => .CompletedProcess
|
||||||
|
|
|
@ -33,6 +33,10 @@ impl LexError {
|
||||||
Self(core)
|
Self(core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_hint<S: Into<AtomicStr>>(&mut self, hint: S) {
|
||||||
|
self.0.hint = Some(hint.into());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
|
||||||
Self::new(ErrorCore::new(
|
Self::new(ErrorCore::new(
|
||||||
errno,
|
errno,
|
||||||
|
|
|
@ -349,7 +349,7 @@ impl Parser {
|
||||||
if self.cur_is(TokenKind::AtSign) {
|
if self.cur_is(TokenKind::AtSign) {
|
||||||
self.lpop();
|
self.lpop();
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Some(Decorator::new(expr)))
|
Ok(Some(Decorator::new(expr)))
|
||||||
|
@ -436,7 +436,7 @@ impl Parser {
|
||||||
Some(semi) if semi.is(Semi) => {
|
Some(semi) if semi.is(Semi) => {
|
||||||
self.lpop();
|
self.lpop();
|
||||||
let len = self
|
let len = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
return Ok(ArrayInner::WithLength(elems.remove_pos(0), len));
|
return Ok(ArrayInner::WithLength(elems.remove_pos(0), len));
|
||||||
|
@ -493,7 +493,7 @@ impl Parser {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(PosArg::new(expr))
|
Ok(PosArg::new(expr))
|
||||||
|
@ -667,7 +667,6 @@ impl Parser {
|
||||||
}
|
}
|
||||||
if self.nth_is(1, Walrus) {
|
if self.nth_is(1, Walrus) {
|
||||||
let acc = self.try_reduce_acc_lhs().map_err(|_| self.stack_dec())?;
|
let acc = self.try_reduce_acc_lhs().map_err(|_| self.stack_dec())?;
|
||||||
// TODO: type specification
|
|
||||||
debug_power_assert!(self.cur_is(Walrus));
|
debug_power_assert!(self.cur_is(Walrus));
|
||||||
self.skip();
|
self.skip();
|
||||||
let kw = if let Accessor::Ident(n) = acc {
|
let kw = if let Accessor::Ident(n) = acc {
|
||||||
|
@ -680,21 +679,52 @@ impl Parser {
|
||||||
return Err(());
|
return Err(());
|
||||||
};
|
};
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, in_type_args, false)
|
.try_reduce_expr(false, in_type_args, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(PosOrKwArg::Kw(KwArg::new(kw, None, expr)))
|
Ok(PosOrKwArg::Kw(KwArg::new(kw, None, expr)))
|
||||||
} else {
|
} else {
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, in_type_args, false)
|
.try_reduce_expr(false, in_type_args, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
if self.cur_is(Walrus) {
|
||||||
|
self.skip();
|
||||||
|
let (kw, t_spec) = match expr {
|
||||||
|
Expr::Accessor(Accessor::Ident(n)) => (n.name.into_token(), None),
|
||||||
|
Expr::TypeAsc(tasc) => {
|
||||||
|
if let Expr::Accessor(Accessor::Ident(n)) = *tasc.expr {
|
||||||
|
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
||||||
|
(n.name.into_token(), Some(t_spec))
|
||||||
|
} else {
|
||||||
|
self.next_expr();
|
||||||
|
self.level -= 1;
|
||||||
|
let err = ParseError::simple_syntax_error(0, tasc.loc());
|
||||||
|
self.errs.push(err);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.next_expr();
|
||||||
|
self.level -= 1;
|
||||||
|
let err = ParseError::simple_syntax_error(0, expr.loc());
|
||||||
|
self.errs.push(err);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let expr = self
|
||||||
|
.try_reduce_expr(false, in_type_args, false, false)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(PosOrKwArg::Kw(KwArg::new(kw, t_spec, expr)))
|
||||||
|
} else {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(PosOrKwArg::Pos(PosArg::new(expr)))
|
Ok(PosOrKwArg::Pos(PosArg::new(expr)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, in_type_args, false)
|
.try_reduce_expr(false, in_type_args, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(PosOrKwArg::Pos(PosArg::new(expr)))
|
Ok(PosOrKwArg::Pos(PosArg::new(expr)))
|
||||||
|
@ -731,7 +761,7 @@ impl Parser {
|
||||||
None
|
None
|
||||||
};*/
|
};*/
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, in_type_args, false)
|
.try_reduce_expr(false, in_type_args, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(KwArg::new(keyword, None, expr))
|
Ok(KwArg::new(keyword, None, expr))
|
||||||
|
@ -834,7 +864,7 @@ impl Parser {
|
||||||
Ok(Lambda::new(sig, op, body, self.counter))
|
Ok(Lambda::new(sig, op, body, self.counter))
|
||||||
} else {
|
} else {
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(true, false, false)
|
.try_reduce_expr(true, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let block = Block::new(vec![expr]);
|
let block = Block::new(vec![expr]);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -901,7 +931,7 @@ impl Parser {
|
||||||
let op = self.lpop();
|
let op = self.lpop();
|
||||||
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
let t_spec = self
|
let t_spec = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
||||||
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
||||||
|
@ -1055,7 +1085,7 @@ impl Parser {
|
||||||
};
|
};
|
||||||
self.skip();
|
self.skip();
|
||||||
let index = self
|
let index = self
|
||||||
.try_reduce_expr(false, false, in_brace)
|
.try_reduce_expr(false, false, in_brace, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let r_sqbr = self.lpop();
|
let r_sqbr = self.lpop();
|
||||||
if !r_sqbr.is(RSqBr) {
|
if !r_sqbr.is(RSqBr) {
|
||||||
|
@ -1071,7 +1101,7 @@ impl Parser {
|
||||||
Some(t) if t.is(Comma) && winding => {
|
Some(t) if t.is(Comma) && winding => {
|
||||||
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
let tup = self
|
let tup = self
|
||||||
.try_reduce_tuple(first_elem)
|
.try_reduce_tuple(first_elem, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
||||||
}
|
}
|
||||||
|
@ -1131,6 +1161,7 @@ impl Parser {
|
||||||
winding: bool,
|
winding: bool,
|
||||||
in_type_args: bool,
|
in_type_args: bool,
|
||||||
in_brace: bool,
|
in_brace: bool,
|
||||||
|
line_break: bool,
|
||||||
) -> ParseResult<Expr> {
|
) -> ParseResult<Expr> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let mut stack = Vec::<ExprOrOp>::new();
|
let mut stack = Vec::<ExprOrOp>::new();
|
||||||
|
@ -1167,7 +1198,7 @@ impl Parser {
|
||||||
let op = self.lpop();
|
let op = self.lpop();
|
||||||
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
let t_spec = self
|
let t_spec = self
|
||||||
.try_reduce_expr(false, in_type_args, in_brace)
|
.try_reduce_expr(false, in_type_args, in_brace, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
||||||
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
||||||
|
@ -1237,7 +1268,7 @@ impl Parser {
|
||||||
Some(t) if t.is(Comma) && winding => {
|
Some(t) if t.is(Comma) && winding => {
|
||||||
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
let tup = self
|
let tup = self
|
||||||
.try_reduce_tuple(first_elem)
|
.try_reduce_tuple(first_elem, line_break)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
||||||
}
|
}
|
||||||
|
@ -1348,6 +1379,15 @@ impl Parser {
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LParen) => {
|
Some(t) if t.is(LParen) => {
|
||||||
let lparen = self.lpop();
|
let lparen = self.lpop();
|
||||||
|
while self.cur_is(Newline) {
|
||||||
|
self.skip();
|
||||||
|
}
|
||||||
|
let line_break = if self.cur_is(Indent) {
|
||||||
|
self.skip();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
if self.cur_is(RParen) {
|
if self.cur_is(RParen) {
|
||||||
let rparen = self.lpop();
|
let rparen = self.lpop();
|
||||||
let args = Args::new(vec![], vec![], Some((lparen, rparen)));
|
let args = Args::new(vec![], vec![], Some((lparen, rparen)));
|
||||||
|
@ -1356,8 +1396,14 @@ impl Parser {
|
||||||
return Ok(Expr::Tuple(unit));
|
return Ok(Expr::Tuple(unit));
|
||||||
}
|
}
|
||||||
let mut expr = self
|
let mut expr = self
|
||||||
.try_reduce_expr(true, false, false)
|
.try_reduce_expr(true, false, false, line_break)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
while self.cur_is(Newline) {
|
||||||
|
self.skip();
|
||||||
|
}
|
||||||
|
if self.cur_is(Dedent) {
|
||||||
|
self.skip();
|
||||||
|
}
|
||||||
let rparen = self.lpop();
|
let rparen = self.lpop();
|
||||||
if let Expr::Tuple(Tuple::Normal(tup)) = &mut expr {
|
if let Expr::Tuple(Tuple::Normal(tup)) = &mut expr {
|
||||||
tup.elems.paren = Some((lparen, rparen));
|
tup.elems.paren = Some((lparen, rparen));
|
||||||
|
@ -1436,7 +1482,7 @@ impl Parser {
|
||||||
Some(t) if t.is(LSqBr) && obj.col_end() == t.col_begin() => {
|
Some(t) if t.is(LSqBr) && obj.col_end() == t.col_begin() => {
|
||||||
let _l_sqbr = self.lpop();
|
let _l_sqbr = self.lpop();
|
||||||
let index = self
|
let index = self
|
||||||
.try_reduce_expr(true, false, false)
|
.try_reduce_expr(true, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let r_sqbr = if self.cur_is(RSqBr) {
|
let r_sqbr = if self.cur_is(RSqBr) {
|
||||||
self.lpop()
|
self.lpop()
|
||||||
|
@ -1556,7 +1602,7 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let op = self.lpop();
|
let op = self.lpop();
|
||||||
let expr = self
|
let expr = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(UnaryOp::new(op, expr))
|
Ok(UnaryOp::new(op, expr))
|
||||||
|
@ -1856,7 +1902,7 @@ impl Parser {
|
||||||
return Ok(dict);
|
return Ok(dict);
|
||||||
}
|
}
|
||||||
let key = self
|
let key = self
|
||||||
.try_reduce_expr(false, false, true)
|
.try_reduce_expr(false, false, true, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
if self.cur_is(Colon) {
|
if self.cur_is(Colon) {
|
||||||
self.skip();
|
self.skip();
|
||||||
|
@ -1889,7 +1935,7 @@ impl Parser {
|
||||||
if self.cur_is(Semi) {
|
if self.cur_is(Semi) {
|
||||||
self.skip();
|
self.skip();
|
||||||
let len = self
|
let len = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let r_brace = self.lpop();
|
let r_brace = self.lpop();
|
||||||
return Ok(Set::WithLength(SetWithLength::new(
|
return Ok(Set::WithLength(SetWithLength::new(
|
||||||
|
@ -1947,19 +1993,22 @@ impl Parser {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_reduce_tuple(&mut self, first_elem: Expr) -> ParseResult<Tuple> {
|
fn try_reduce_tuple(&mut self, first_elem: Expr, line_break: bool) -> ParseResult<Tuple> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let mut args = Args::new(vec![PosArg::new(first_elem)], vec![], None);
|
let mut args = Args::new(vec![PosArg::new(first_elem)], vec![], None);
|
||||||
loop {
|
loop {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Comma) => {
|
Some(t) if t.is(Comma) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
|
while self.cur_is(Newline) && line_break {
|
||||||
|
self.skip();
|
||||||
|
}
|
||||||
if self.cur_is(Comma) {
|
if self.cur_is(Comma) {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
return Err(());
|
return Err(());
|
||||||
} else if self.cur_is(RParen) {
|
} else if self.cur_is(Dedent) || self.cur_is(RParen) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match self.try_reduce_arg(false).map_err(|_| self.stack_dec())? {
|
match self.try_reduce_arg(false).map_err(|_| self.stack_dec())? {
|
||||||
|
@ -2916,6 +2965,13 @@ impl Parser {
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::Lit(lit) => {
|
||||||
|
let mut err = ParseError::simple_syntax_error(line!() as usize, lit.loc());
|
||||||
|
if lit.is(TokenKind::NoneLit) {
|
||||||
|
err.set_hint("you mean: `NoneType`?");
|
||||||
|
}
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||||
Err(err)
|
Err(err)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
math = pyimport "math"
|
math = pyimport "math"
|
||||||
sys = pyimport "sys"
|
sys = pyimport "sys"
|
||||||
|
sub = pyimport "subprocess"
|
||||||
|
|
||||||
print! math.pi
|
print! math.pi
|
||||||
|
discard sub.run! ["echo", "hello"], shell := True
|
||||||
sys.exit 111
|
sys.exit 111
|
||||||
|
|
|
@ -2,13 +2,15 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::error::MultiErrorDisplay;
|
use erg_common::error::MultiErrorDisplay;
|
||||||
use erg_common::traits::Runnable;
|
use erg_common::traits::{Runnable, Stream};
|
||||||
|
|
||||||
|
use erg_compiler::error::CompileErrors;
|
||||||
|
|
||||||
use erg::dummy::DummyVM;
|
use erg::dummy::DummyVM;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_addition() -> Result<(), ()> {
|
fn exec_addition() -> Result<(), ()> {
|
||||||
expect_failure("tests/addition.er")
|
expect_failure("tests/addition.er", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -63,7 +65,7 @@ fn exec_infer_trait() -> Result<(), ()> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_move_check() -> Result<(), ()> {
|
fn exec_move_check() -> Result<(), ()> {
|
||||||
expect_failure("examples/move_check.er")
|
expect_failure("examples/move_check.er", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -89,17 +91,17 @@ fn exec_record() -> Result<(), ()> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_set() -> Result<(), ()> {
|
fn exec_set() -> Result<(), ()> {
|
||||||
expect_failure("examples/set.er")
|
expect_failure("examples/set.er", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_side_effect() -> Result<(), ()> {
|
fn exec_side_effect() -> Result<(), ()> {
|
||||||
expect_failure("examples/side_effect.er")
|
expect_failure("examples/side_effect.er", 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_subtyping() -> Result<(), ()> {
|
fn exec_subtyping() -> Result<(), ()> {
|
||||||
expect_failure("tests/subtyping.er")
|
expect_failure("tests/subtyping.er", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -128,9 +130,7 @@ fn exec_with() -> Result<(), ()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_success(file_path: &'static str) -> Result<(), ()> {
|
fn expect_success(file_path: &'static str) -> Result<(), ()> {
|
||||||
let cfg = ErgConfig::with_main_path(PathBuf::from(file_path));
|
match exec_vm(file_path) {
|
||||||
let mut vm = DummyVM::new(cfg);
|
|
||||||
match vm.exec() {
|
|
||||||
Ok(0) => Ok(()),
|
Ok(0) => Ok(()),
|
||||||
Ok(i) => {
|
Ok(i) => {
|
||||||
println!("err: end with {i}");
|
println!("err: end with {i}");
|
||||||
|
@ -144,9 +144,7 @@ fn expect_success(file_path: &'static str) -> Result<(), ()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_end_with(file_path: &'static str, code: i32) -> Result<(), ()> {
|
fn expect_end_with(file_path: &'static str, code: i32) -> Result<(), ()> {
|
||||||
let cfg = ErgConfig::with_main_path(PathBuf::from(file_path));
|
match exec_vm(file_path) {
|
||||||
let mut vm = DummyVM::new(cfg);
|
|
||||||
match vm.exec() {
|
|
||||||
Ok(0) => Err(()),
|
Ok(0) => Err(()),
|
||||||
Ok(i) => {
|
Ok(i) => {
|
||||||
if i == code {
|
if i == code {
|
||||||
|
@ -163,15 +161,41 @@ fn expect_end_with(file_path: &'static str, code: i32) -> Result<(), ()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_failure(file_path: &'static str) -> Result<(), ()> {
|
fn expect_failure(file_path: &'static str, errs_len: usize) -> Result<(), ()> {
|
||||||
let cfg = ErgConfig::with_main_path(PathBuf::from(file_path));
|
match exec_vm(file_path) {
|
||||||
let mut vm = DummyVM::new(cfg);
|
|
||||||
match vm.exec() {
|
|
||||||
Ok(0) => Err(()),
|
Ok(0) => Err(()),
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(errs) => {
|
Err(errs) => {
|
||||||
errs.fmt_all_stderr();
|
errs.fmt_all_stderr();
|
||||||
|
if errs.len() == errs_len {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
println!("err: error length is not {errs_len} but {}", errs.len());
|
||||||
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _exec_vm(file_path: &'static str) -> Result<i32, CompileErrors> {
|
||||||
|
let cfg = ErgConfig::with_main_path(PathBuf::from(file_path));
|
||||||
|
let mut vm = DummyVM::new(cfg);
|
||||||
|
vm.exec()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn exec_vm(file_path: &'static str) -> Result<i32, CompileErrors> {
|
||||||
|
const STACK_SIZE: usize = 4 * 1024 * 1024;
|
||||||
|
|
||||||
|
let child = std::thread::Builder::new()
|
||||||
|
.stack_size(STACK_SIZE)
|
||||||
|
.spawn(move || _exec_vm(file_path))
|
||||||
|
.unwrap();
|
||||||
|
// Wait for thread to join
|
||||||
|
child.join().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn exec_vm(file_path: &'static str) -> Result<i32, CompileErrors> {
|
||||||
|
_exec_vm(file_path)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue