diff --git a/src/ast.rs b/src/ast.rs index 168ffd96..c8577d6d 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -107,6 +107,7 @@ pub enum AstExpressionBody { IVarRef(String), ConstRef(Vec), PseudoVariable(Token), + ArrayLiteral(Vec), FloatLiteral { value: f64, }, @@ -294,6 +295,10 @@ pub fn pseudo_variable(token: Token) -> AstExpression { primary_expression(AstExpressionBody::PseudoVariable(token)) } +pub fn array_literal(exprs: Vec) -> AstExpression { + primary_expression(AstExpressionBody::ArrayLiteral(exprs)) +} + pub fn float_literal(value: f64) -> AstExpression { primary_expression(AstExpressionBody::FloatLiteral{ value }) } diff --git a/src/code_gen/gen_exprs.rs b/src/code_gen/gen_exprs.rs index 6577a5b5..52f950db 100644 --- a/src/code_gen/gen_exprs.rs +++ b/src/code_gen/gen_exprs.rs @@ -74,6 +74,9 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { HirSelfExpression => { self.gen_self_expression(ctx) }, + HirArrayLiteral { exprs: _ } => { + panic!("TODO") + } HirFloatLiteral { value } => { Ok(self.gen_float_literal(*value)) }, @@ -92,9 +95,6 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { HirClassLiteral { fullname, str_literal_idx } => { Ok(self.gen_class_literal(fullname, str_literal_idx)) } -// _ => { -// panic!("TODO: {:?}", expr.node) -// } } } diff --git a/src/hir/convert_exprs.rs b/src/hir/convert_exprs.rs index 0f6e610f..60b8e3a1 100644 --- a/src/hir/convert_exprs.rs +++ b/src/hir/convert_exprs.rs @@ -75,6 +75,10 @@ impl HirMaker { self.convert_pseudo_variable(ctx, token) }, + AstExpressionBody::ArrayLiteral(exprs) => { + self.convert_array_literal(ctx, exprs) + }, + AstExpressionBody::FloatLiteral {value} => { Ok(Hir::float_literal(*value)) }, @@ -370,6 +374,16 @@ impl HirMaker { } } + fn convert_array_literal(&mut self, + ctx: &mut HirMakerContext, + exprs: &[AstExpression]) -> Result { + let hir_exprs = exprs.iter().map(|expr| + self.convert_expr(ctx, expr) + ).collect::, _>>()?; + + Ok(Hir::array_literal(hir_exprs)) + } + fn convert_self_expr(&self, ctx: &HirMakerContext) -> Result { Ok(Hir::self_expression(ctx.self_ty.clone())) } diff --git a/src/hir/mod.rs b/src/hir/mod.rs index 30cb0e97..b2352926 100644 --- a/src/hir/mod.rs +++ b/src/hir/mod.rs @@ -177,6 +177,9 @@ pub enum HirExpressionBase { fullname: ConstFullname, }, HirSelfExpression, + HirArrayLiteral { + exprs: Vec, + }, HirFloatLiteral { value: f64, }, @@ -347,6 +350,14 @@ impl Hir { } } + pub fn array_literal(exprs: Vec) -> HirExpression { + HirExpression { + // TODO: infer more specific type from the elements + ty: ty::spe("Array", vec![ty::raw("Object")]), + node: HirExpressionBase::HirArrayLiteral { exprs } + } + } + pub fn float_literal(value: f64) -> HirExpression { HirExpression { ty: ty::raw("Float"), diff --git a/src/parser/expression_parser.rs b/src/parser/expression_parser.rs index 1ee3de4b..c9570239 100644 --- a/src/parser/expression_parser.rs +++ b/src/parser/expression_parser.rs @@ -599,6 +599,9 @@ impl<'a> Parser<'a> { self.consume_token(); Ok(ast::ivar_ref(name)) }, + Token::LSqBracket => { + self.parse_array_literal() + }, Token::Number(_) => { self.parse_decimal_literal() }, @@ -660,15 +663,47 @@ impl<'a> Parser<'a> { self.lv += 1; self.debug_log("parse_parenthesized_expr"); assert!(self.consume(Token::LParen)); self.skip_wsn(); - let expr = self.parse_expr()?; // Should be parse_stmts() ? + let expr = self.parse_expr()?; // Should be parse_exprs() ? self.skip_wsn(); self.expect(Token::RParen)?; self.lv -= 1; Ok(expr) } + fn parse_array_literal(&mut self) -> Result { + self.lv += 1; self.debug_log("parse_array_literal"); + assert!(self.consume(Token::LSqBracket)); + let mut exprs = vec![]; + self.skip_wsn(); + loop { + match self.current_token() { + Token::RSqBracket => { + self.consume_token(); + break + }, + Token::Comma => { + return Err(parse_error!(self, "unexpected comma in an array literal")) + }, + _ => { + let expr = self.parse_expr()?; + exprs.push(expr); + self.skip_wsn(); + match self.current_token() { + Token::Comma => { self.consume_token(); }, + Token::RSqBracket => (), + token => { + return Err(parse_error!(self, "unexpected token `{:?}' in an array literal", token)) + } + } + } + } + } + self.lv -= 1; + Ok(ast::array_literal(exprs)) + } + fn parse_decimal_literal(&mut self) -> Result { - self.lv += 1; self.debug_log("parse_parenthesized_expr"); + self.lv += 1; self.debug_log("parse_decimal_literal"); let expr = match self.consume_token() { Token::Number(s) => { if s.contains('.') { diff --git a/src/ty.rs b/src/ty.rs index a6e0e5a9..6e42c15c 100644 --- a/src/ty.rs +++ b/src/ty.rs @@ -33,6 +33,21 @@ pub enum TyBody { TyMeta { base_fullname: String }, // This object belongs to the class `Class` (i.e. this is a class object) TyClass, + // Types for generic metaclass eg. `Meta:Pair` + TyGenMeta { + base_name: String, // eg. "Pair" + typaram_names: Vec, // eg. ["S", "T"] (For debug print) + }, + // Types for specialized class eg. `Pair` + TySpe { + base_name: String, // eg. "Pair" + type_args: Vec, + }, + // Types for specialized metaclass eg. `Meta:Pair` + TySpeMeta { + base_name: String, // eg. "Pair" + type_args: Vec, + }, } use TyBody::*; @@ -46,65 +61,23 @@ impl TermTy { } } - pub fn is_nonmeta(&self) -> bool { - match self.body { - TyRaw => true, - _ => false, - } - } - pub fn meta_ty(&self) -> TermTy { match self.body { TyRaw => ty::meta(&self.fullname.0), TyMeta { .. } => ty::class(), TyClass => ty::class(), + _ => panic!("TODO"), } } pub fn conforms_to(&self, other: &TermTy) -> bool { - match self.body { - TyRaw => { - match other.body { - TyRaw => (self.fullname == other.fullname), - _ => false, - } - }, - TyMeta { .. } => { - match other.body { - TyMeta { .. } => (self.fullname == other.fullname), - _ => false, - } - }, - TyClass => { - match other.body { - TyClass => true, - _ => false, - } - } - } + // TODO: Should respect class hierarchy + self.equals_to(other) } + /// Return true if two types are identical pub fn equals_to(&self, other: &TermTy) -> bool { - match self.body { - TyRaw => { - match other.body { - TyRaw => (self.fullname == other.fullname), - _ => false, - } - }, - TyMeta { .. } => { - match other.body { - TyMeta { .. } => (self.fullname == other.fullname), - _ => false, - } - }, - TyClass => { - match other.body { - TyClass => true, - _ => false, - } - } - } + self == other } } @@ -126,6 +99,19 @@ pub fn class() -> TermTy { } } +pub fn spe(base_name: &str, type_args: Vec) -> TermTy { + let tyarg_names = type_args.iter().map(|x| { + x.fullname.0.to_string() + }).collect::>(); + TermTy { + fullname: class_fullname(&format!("{}<{}>", &base_name, &tyarg_names.join(","))), + body: TySpe { + base_name: base_name.to_string(), + type_args + } + } +} + // Types corresponds to (non-specialized) generic class //pub struct TyGen {} // Note: TyGen does not implement TermTy (Generic class itself cannot have an instance)