diff --git a/compiler/erg_common/python_util.rs b/compiler/erg_common/python_util.rs index 05a43bfb..df00fd9c 100644 --- a/compiler/erg_common/python_util.rs +++ b/compiler/erg_common/python_util.rs @@ -6,7 +6,7 @@ use std::process::Command; use crate::serialize::get_magic_num_from_bytes; #[cfg(unix)] -pub const BUILTIN_PYTHON_MODS: [&str; 20] = [ +pub const BUILTIN_PYTHON_MODS: [&str; 21] = [ "datetime", "glob", "http", @@ -15,6 +15,7 @@ pub const BUILTIN_PYTHON_MODS: [&str; 20] = [ "json", "math", "os", + "platform", "posix", "random", "re", @@ -29,7 +30,7 @@ pub const BUILTIN_PYTHON_MODS: [&str; 20] = [ "zipfile", ]; #[cfg(not(unix))] -pub const BUILTIN_PYTHON_MODS: [&str; 19] = [ +pub const BUILTIN_PYTHON_MODS: [&str; 20] = [ "datetime", "glob", "http", @@ -38,6 +39,7 @@ pub const BUILTIN_PYTHON_MODS: [&str; 19] = [ "json", "math", "os", + "platform", "random", "re", "shutil", diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 4f8dffe8..23151077 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -956,6 +956,22 @@ impl Context { } Ok(dict_t(inst_tys.into())) } + TypeSpec::Record(rec) => { + let mut inst_tys = dict! {}; + for (k, v) in rec { + inst_tys.insert( + k.into(), + self.instantiate_typespec( + v, + opt_decl_t, + tmp_tv_ctx, + mode, + not_found_is_qvar, + )?, + ); + } + Ok(Type::Record(inst_tys)) + } // TODO: エラー処理(リテラルでない)はパーサーにやらせる TypeSpec::Enum(set) => { let mut new_set = set! {}; diff --git a/compiler/erg_compiler/lib/pystd/platform.d.er b/compiler/erg_compiler/lib/pystd/platform.d.er new file mode 100644 index 00000000..33893311 --- /dev/null +++ b/compiler/erg_compiler/lib/pystd/platform.d.er @@ -0,0 +1,13 @@ +.architecture!: () => Str +.machine!: () => Str +.node!: () => Str +.platform!: () => Str +.processor!: () => Str +.python_build!: () => Str +.python_compiler!: () => Str +.python_branch!: () => Str +.python_implementation!: () => Str +.python_revision!: () => Str +.python_version!: () => Str +.python_version_tuple!: () => (Str, Str, Str) +.uname!: () => {.system = Str; .node = Str; .release = Str; .version = Str; .machine = Str} diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index c63c17dc..2a126dcc 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1768,7 +1768,7 @@ pub enum TypeSpec { Set(SetTypeSpec), Tuple(Vec), Dict(Vec<(TypeSpec, TypeSpec)>), - // Dict(), + Record(Vec<(Identifier, TypeSpec)>), // Option(), And(Box, Box), Not(Box, Box), @@ -1799,11 +1799,18 @@ impl fmt::Display for TypeSpec { Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)), Self::Dict(dict) => { write!(f, "{{")?; - for (k, v) in dict { + for (k, v) in dict.iter() { write!(f, "{k}: {v}, ")?; } write!(f, "}}") } + Self::Record(rec) => { + write!(f, "{{")?; + for (k, v) in rec.iter() { + write!(f, "{k} = {v}; ")?; + } + write!(f, "}}") + } Self::Enum(elems) => write!(f, "{{{elems}}}"), Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()), Self::Subr(s) => write!(f, "{s}"), @@ -1824,6 +1831,7 @@ impl Locational for TypeSpec { // TODO: ユニット Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()), Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1), + Self::Record(rec) => Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1), Self::Enum(set) => set.loc(), Self::Interval { lhs, rhs, .. } => Location::concat(lhs, rhs), Self::Subr(s) => s.loc(), diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 938febb1..23b9995e 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -3046,6 +3046,38 @@ impl Parser { } } + fn record_to_record_type_spec( + record: Record, + ) -> Result, ParseError> { + match record { + Record::Normal(rec) => { + let mut rec_spec = vec![]; + for mut def in rec.attrs.into_iter() { + let ident = def.sig.ident().unwrap().clone(); + // TODO: check block.len() == 1 + let value = Self::expr_to_type_spec(def.body.block.pop().unwrap())?; + rec_spec.push((ident, value)); + } + Ok(rec_spec) + } + _ => todo!(), + } + } + + fn tuple_to_tuple_type_spec(tuple: Tuple) -> Result, ParseError> { + match tuple { + Tuple::Normal(tup) => { + let mut tup_spec = vec![]; + let (elems, ..) = tup.elems.deconstruct(); + for elem in elems.into_iter() { + let value = Self::expr_to_type_spec(elem.expr)?; + tup_spec.push(value); + } + Ok(tup_spec) + } + } + } + pub fn expr_to_type_spec(rhs: Expr) -> Result { match rhs { Expr::Accessor(acc) => Self::accessor_to_type_spec(acc), @@ -3069,6 +3101,14 @@ impl Parser { let dict = Self::dict_to_dict_type_spec(dict)?; Ok(TypeSpec::Dict(dict)) } + Expr::Record(rec) => { + let rec = Self::record_to_record_type_spec(rec)?; + Ok(TypeSpec::Record(rec)) + } + Expr::Tuple(tup) => { + let tup = Self::tuple_to_tuple_type_spec(tup)?; + Ok(TypeSpec::Tuple(tup)) + } Expr::BinOp(bin) => { if bin.op.kind.is_range_op() { let op = bin.op;