Skip to content

Commit

Permalink
frontend: Allow unnamed access to classes and structs
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Nov 1, 2024
1 parent 0f9c237 commit e02e2ad
Show file tree
Hide file tree
Showing 13 changed files with 222 additions and 39 deletions.
29 changes: 24 additions & 5 deletions dora-bytecode/src/dumper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,18 @@ pub fn dump(w: &mut dyn io::Write, prog: &Program, bc: &BytecodeFunction) -> std
let struct_ = prog.struct_(*struct_id);
let struct_name = module_path_name(prog, struct_.module_id, &struct_.name);
let field = &struct_.fields[*field_idx as usize];
let name = if let Some(ref name) = field.name {
name
} else {
&field_idx.to_string()
};
writeln!(
w,
"{}{} => StructField {}.{}",
align,
idx,
fmt_name(prog, &struct_name, &type_params),
field.name
name
)?;
}
ConstPoolEntry::Enum(enum_id, type_params) => {
Expand Down Expand Up @@ -124,13 +129,18 @@ pub fn dump(w: &mut dyn io::Write, prog: &Program, bc: &BytecodeFunction) -> std
let cls = prog.class(*cls_id);
let cls_name = module_path_name(prog, cls.module_id, &cls.name);
let field = &cls.fields[*field_id as usize];
let name = if let Some(ref name) = field.name {
name
} else {
&field_id.to_string()
};
writeln!(
w,
"{}{} => Field {}.{}",
align,
idx,
fmt_name(prog, &cls_name, &type_params),
field.name
name
)?;
}
ConstPoolEntry::Fct(fct_id, type_params) => {
Expand Down Expand Up @@ -429,21 +439,30 @@ impl<'a> BytecodeDumper<'a> {
ConstPoolEntry::Field(cls_id, type_params, field_id) => {
let cls = self.prog.class(*cls_id);
let field = &cls.fields[*field_id as usize];

let name = if let Some(ref name) = field.name {
name
} else {
&field_id.to_string()
};
writeln!(
self.w,
" {}, {}, ConstPoolIdx({}) # {}.{}",
r1,
r2,
field_idx.0,
fmt_name(self.prog, &cls.name, type_params),
field.name,
name,
)
.expect("write! failed");
}
ConstPoolEntry::StructField(struct_id, type_params, field_id) => {
let struct_ = self.prog.struct_(*struct_id);
let field = &struct_.fields[*field_id as usize];
let name = if let Some(ref name) = field.name {
name
} else {
&field_id.to_string()
};

writeln!(
self.w,
Expand All @@ -452,7 +471,7 @@ impl<'a> BytecodeDumper<'a> {
r2,
field_idx.0,
fmt_name(self.prog, &struct_.name, type_params),
field.name,
name,
)
.expect("write! failed");
}
Expand Down
4 changes: 2 additions & 2 deletions dora-bytecode/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub struct ClassData {
#[derive(Debug, Decode, Encode)]
pub struct ClassField {
pub ty: BytecodeType,
pub name: String,
pub name: Option<String>,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Decode, Encode)]
Expand All @@ -98,7 +98,7 @@ pub struct StructData {
#[derive(Debug, Decode, Encode)]
pub struct StructField {
pub ty: BytecodeType,
pub name: String,
pub name: Option<String>,
}

#[derive(Debug, Decode, Encode)]
Expand Down
2 changes: 1 addition & 1 deletion dora-frontend/src/error/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub enum ErrorMessage {
MatchBranchTypesIncompatible(String, String),
NameExpected,
IndexExpected,
IllegalTupleIndex(u64, String),
IllegalTupleIndex(usize, String),
UninitializedVar,
DirectoryNotFound(PathBuf),
FileForModuleNotFound,
Expand Down
4 changes: 2 additions & 2 deletions dora-frontend/src/program_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ fn create_class_fields(sa: &Sema, class: &ClassDefinition) -> Vec<ClassField> {
.iter()
.map(|f| ClassField {
ty: bty_from_ty(f.ty()),
name: sa.interner.str(f.name).to_string(),
name: f.name.map(|n| sa.interner.str(n).to_string()),
})
.collect()
}
Expand Down Expand Up @@ -337,7 +337,7 @@ fn create_struct_fields(sa: &Sema, struct_: &StructDefinition) -> Vec<StructFiel
.iter()
.map(|f| StructField {
ty: bty_from_ty(f.ty()),
name: sa.interner.str(f.name).to_string(),
name: f.name.map(|n| sa.interner.str(n).to_string()),
})
.collect()
}
Expand Down
20 changes: 14 additions & 6 deletions dora-frontend/src/program_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,9 +567,13 @@ impl<'x> visit::Visitor for TopLevelDeclaration<'x> {
let modifiers =
check_modifiers(self.sa, self.file_id, &field.modifiers, &[Annotation::Pub]);

let name = ensure_name(self.sa, &field.name);

check_if_symbol_exists(self.sa, self.file_id, &mut used_names, name, field.span);
let name = if node.field_name_style.is_positional() {
None
} else {
let name = ensure_name(self.sa, &field.name);
check_if_symbol_exists(self.sa, self.file_id, &mut used_names, name, field.span);
Some(name)
};

fields.push(Field {
id: FieldId(idx),
Expand Down Expand Up @@ -627,9 +631,13 @@ impl<'x> visit::Visitor for TopLevelDeclaration<'x> {
let modifiers =
check_modifiers(self.sa, self.file_id, &field.modifiers, &[Annotation::Pub]);

let name = ensure_name(self.sa, &field.name);

check_if_symbol_exists(self.sa, self.file_id, &mut used_names, name, field.span);
let name = if node.field_style.is_positional() {
None
} else {
let name = ensure_name(self.sa, &field.name);
check_if_symbol_exists(self.sa, self.file_id, &mut used_names, name, field.span);
Some(name)
};

fields.push(StructDefinitionField {
id: StructDefinitionFieldId(idx),
Expand Down
10 changes: 5 additions & 5 deletions dora-frontend/src/sema/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ impl ClassDefinition {

pub fn field_by_name(&self, name: Name) -> FieldId {
for field in &self.fields {
if field.name == name {
if field.name == Some(name) {
return field.id;
}
}
Expand Down Expand Up @@ -229,7 +229,7 @@ impl ElementAccess for ClassDefinition {

impl ElementWithFields for ClassDefinition {
fn field_name(&self, idx: usize) -> Name {
self.fields[idx].name
self.fields[idx].name.expect("name expected")
}

fn fields_len(&self) -> usize {
Expand All @@ -239,7 +239,7 @@ impl ElementWithFields for ClassDefinition {
fn fields<'a>(&'a self) -> Box<dyn Iterator<Item = ElementField> + 'a> {
Box::new(self.fields.iter().map(|f| ElementField {
id: f.id.to_usize(),
name: f.name,
name: f.name.expect("name expected"),
ty: f.ty(),
}))
}
Expand All @@ -263,7 +263,7 @@ impl From<usize> for FieldId {
#[derive(Debug)]
pub struct Field {
pub id: FieldId,
pub name: Name,
pub name: Option<Name>,
pub parsed_ty: ParsedType,
pub mutable: bool,
pub visibility: Visibility,
Expand Down Expand Up @@ -302,7 +302,7 @@ pub fn find_field_in_class(
let cls = sa.class(cls_id);

for field in &cls.fields {
if field.name == name {
if field.name == Some(name) {
return Some((
field.id,
specialize_for_element(sa, field.ty(), cls, &type_params),
Expand Down
16 changes: 9 additions & 7 deletions dora-frontend/src/sema/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ impl StructDefinition {
let mut field_names = HashMap::new();

for field in &fields {
if field_names.contains_key(&field.name) {
continue;
}
if let Some(name) = field.name {
if field_names.contains_key(&name) {
continue;
}

field_names.insert(field.name, field.id);
field_names.insert(name, field.id);
}
}

StructDefinition {
Expand Down Expand Up @@ -185,13 +187,13 @@ impl ElementWithFields for StructDefinition {
}

fn field_name(&self, idx: usize) -> Name {
self.fields[idx].name
self.fields[idx].name.expect("name expected")
}

fn fields<'a>(&'a self) -> Box<dyn Iterator<Item = super::ElementField> + 'a> {
Box::new(self.fields.iter().map(|f| ElementField {
id: f.id.to_usize(),
name: f.name,
name: f.name.expect("name expected"),
ty: f.ty(),
}))
}
Expand All @@ -216,7 +218,7 @@ impl StructDefinitionFieldId {
pub struct StructDefinitionField {
pub id: StructDefinitionFieldId,
pub span: Span,
pub name: Name,
pub name: Option<Name>,
pub parsed_ty: ParsedType,
pub visibility: Visibility,
}
Expand Down
2 changes: 1 addition & 1 deletion dora-frontend/src/stdlib_lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ pub fn create_lambda_class(sa: &mut Sema) {

let field = Field {
id: FieldId(0),
name: context_name,
name: Some(context_name),
parsed_ty: ParsedType::new_ty(SourceType::Ptr),
mutable: false,
visibility: Visibility::Public,
Expand Down
58 changes: 53 additions & 5 deletions dora-frontend/src/typeck/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ fn check_expr_dot_lit_int(

ck.analysis.set_const_value(literal.id, value.clone());

let index = value.to_i64().unwrap_or(0) as u64;
let index = value.to_i64().unwrap_or(0) as usize;

match object_type.clone() {
SourceType::Error
Expand All @@ -523,18 +523,66 @@ fn check_expr_dot_lit_int(
| SourceType::Lambda(..)
| SourceType::Alias(..)
| SourceType::Assoc(..)
| SourceType::GenericAssoc(..)
| SourceType::Class(..)
| SourceType::Struct(..) => {
| SourceType::GenericAssoc(..) => {
let name = index.to_string();
let expr_name = ck.ty_name(&object_type);
let msg = ErrorMessage::UnknownField(name, expr_name);
ck.sa.report(ck.file_id, e.rhs.span(), msg);
SourceType::Error
}

SourceType::Class(class_id, class_type_params) => {
let cls = ck.sa.class(class_id);
if !cls.field_name_style.is_named() && index < cls.fields.len() {
let field = &cls.fields[index];
let ident_type = IdentType::Field(object_type.clone(), field.id);
ck.analysis.map_idents.insert_or_replace(e.id, ident_type);

let fty = replace_type(ck.sa, field.ty(), Some(&class_type_params), None);

if !class_field_accessible_from(ck.sa, class_id, field.id, ck.module_id) {
let msg = ErrorMessage::NotAccessible;
ck.sa.report(ck.file_id, e.rhs.span(), msg);
}

ck.analysis.set_ty(e.id, fty.clone());
fty
} else {
let name = index.to_string();
let expr_name = ck.ty_name(&object_type);
let msg = ErrorMessage::UnknownField(name, expr_name);
ck.sa.report(ck.file_id, e.rhs.span(), msg);
SourceType::Error
}
}

SourceType::Struct(struct_id, struct_type_params) => {
let struct_ = ck.sa.struct_(struct_id);
if !struct_.field_name_style.is_named() && index < struct_.fields.len() {
let field = &struct_.fields[index];
let ident_type = IdentType::StructField(object_type.clone(), field.id);
ck.analysis.map_idents.insert_or_replace(e.id, ident_type);

let fty = replace_type(ck.sa, field.ty(), Some(&struct_type_params), None);

if !struct_field_accessible_from(ck.sa, struct_id, field.id, ck.module_id) {
let msg = ErrorMessage::NotAccessible;
ck.sa.report(ck.file_id, e.rhs.span(), msg);
}

ck.analysis.set_ty(e.id, fty.clone());
fty
} else {
let name = index.to_string();
let expr_name = ck.ty_name(&object_type);
let msg = ErrorMessage::UnknownField(name, expr_name);
ck.sa.report(ck.file_id, e.rhs.span(), msg);
SourceType::Error
}
}

SourceType::Tuple(subtypes) => {
if index >= subtypes.len() as u64 {
if index >= subtypes.len() {
let msg = ErrorMessage::IllegalTupleIndex(index, ck.ty_name(&object_type));
ck.sa.report(ck.file_id, e.op_span, msg);

Expand Down
4 changes: 2 additions & 2 deletions dora-frontend/src/typeck/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl<'a> TypeCheck<'a> {
let name = self.sa.interner.intern("parent_context");
let field = Field {
id: FieldId(0),
name,
name: Some(name),
parsed_ty: ParsedType::new_ty(SourceType::Ptr),
mutable: true,
visibility: Visibility::Module,
Expand All @@ -263,7 +263,7 @@ impl<'a> TypeCheck<'a> {
let id = FieldId(fields.len());
let field = Field {
id,
name: var.name,
name: Some(var.name),
parsed_ty: ParsedType::new_ty(var.ty.clone()),
mutable: true,
visibility: Visibility::Module,
Expand Down
Loading

0 comments on commit e02e2ad

Please sign in to comment.