Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse Array literal #85

Merged
merged 3 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub enum AstExpressionBody {
IVarRef(String),
ConstRef(Vec<String>),
PseudoVariable(Token),
ArrayLiteral(Vec<AstExpression>),
FloatLiteral {
value: f64,
},
Expand Down Expand Up @@ -294,6 +295,10 @@ pub fn pseudo_variable(token: Token) -> AstExpression {
primary_expression(AstExpressionBody::PseudoVariable(token))
}

pub fn array_literal(exprs: Vec<AstExpression>) -> AstExpression {
primary_expression(AstExpressionBody::ArrayLiteral(exprs))
}

pub fn float_literal(value: f64) -> AstExpression {
primary_expression(AstExpressionBody::FloatLiteral{ value })
}
Expand Down
6 changes: 3 additions & 3 deletions src/code_gen/gen_exprs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
},
Expand All @@ -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)
// }
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/hir/convert_exprs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
},
Expand Down Expand Up @@ -370,6 +374,16 @@ impl HirMaker {
}
}

fn convert_array_literal(&mut self,
ctx: &mut HirMakerContext,
exprs: &[AstExpression]) -> Result<HirExpression, Error> {
let hir_exprs = exprs.iter().map(|expr|
self.convert_expr(ctx, expr)
).collect::<Result<Vec<_>, _>>()?;

Ok(Hir::array_literal(hir_exprs))
}

fn convert_self_expr(&self, ctx: &HirMakerContext) -> Result<HirExpression, Error> {
Ok(Hir::self_expression(ctx.self_ty.clone()))
}
Expand Down
11 changes: 11 additions & 0 deletions src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ pub enum HirExpressionBase {
fullname: ConstFullname,
},
HirSelfExpression,
HirArrayLiteral {
exprs: Vec<HirExpression>,
},
HirFloatLiteral {
value: f64,
},
Expand Down Expand Up @@ -347,6 +350,14 @@ impl Hir {
}
}

pub fn array_literal(exprs: Vec<HirExpression>) -> 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"),
Expand Down
39 changes: 37 additions & 2 deletions src/parser/expression_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
},
Expand Down Expand Up @@ -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<AstExpression, Error> {
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<AstExpression, Error> {
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('.') {
Expand Down
80 changes: 33 additions & 47 deletions src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<S, T>`
TyGenMeta {
base_name: String, // eg. "Pair"
typaram_names: Vec<String>, // eg. ["S", "T"] (For debug print)
},
// Types for specialized class eg. `Pair<Int, Bool>`
TySpe {
base_name: String, // eg. "Pair"
type_args: Vec<TermTy>,
},
// Types for specialized metaclass eg. `Meta:Pair<Int, Bool>`
TySpeMeta {
base_name: String, // eg. "Pair"
type_args: Vec<TermTy>,
},
}

use TyBody::*;
Expand All @@ -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
}
}

Expand All @@ -126,6 +99,19 @@ pub fn class() -> TermTy {
}
}

pub fn spe(base_name: &str, type_args: Vec<TermTy>) -> TermTy {
let tyarg_names = type_args.iter().map(|x| {
x.fullname.0.to_string()
}).collect::<Vec<_>>();
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)
Expand Down