Skip to content

Commit

Permalink
feat: add missing bits for for-in, @addField and @replaceGlobal
Browse files Browse the repository at this point in the history
  • Loading branch information
jac3km4 committed Nov 4, 2023
1 parent 0352a86 commit e2caff2
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 11 deletions.
11 changes: 7 additions & 4 deletions compiler/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ impl<'ctx, 'id> CodeGen<'ctx, 'id> {
Constant::Bool(true) => self.emit(Instr::TrueConst),
Constant::Bool(false) => self.emit(Instr::FalseConst),
},
Expr::ArrayLit(_, _, _) => todo!(),
Expr::InterpolatedString(_, _, _) => todo!(),
Expr::Declare(local, typ, init, _) => {
let typ = typ.expect("type should be populated in codegen").simplify(self.repo);
let idx = LocalBuilder::builder()
Expand Down Expand Up @@ -412,8 +410,13 @@ impl<'ctx, 'id> CodeGen<'ctx, 'id> {
Expr::Break(_) => {
self.emit(Instr::Jump(exit.expect("break should have exit label")));
}
Expr::BinOp(_, _, _, _) | Expr::UnOp(_, _, _) | Expr::Goto(_, _) | Expr::ForIn(_, _, _, _) => {
unreachable!()
Expr::BinOp(_, _, _, _)
| Expr::UnOp(_, _, _)
| Expr::Goto(_, _)
| Expr::ArrayLit(_, _, _)
| Expr::InterpolatedString(_, _, _)
| Expr::ForIn(_, _, _, _) => {
unreachable!("this expression should be removed before codegen")
}
}
}
Expand Down
63 changes: 57 additions & 6 deletions compiler/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ impl<'id> Compiler<'id> {
}
MemberSource::Field(field) => {
let flags = get_field_flags(&field.declaration.qualifiers);
self.validate_field(data_type.flags, flags, field.declaration.span);
Self::validate_field(&mut self.reporter, data_type.flags, flags, field.declaration.span);
let env = TypeEnv::new(types, &type_vars);
let res = env.resolve_type(&field.type_).with_span(field.declaration.span);
let Some(typ) = self.reporter.unwrap_err(res) else {
Expand Down Expand Up @@ -350,9 +350,28 @@ impl<'id> Compiler<'id> {
let data = Data::without_args(id);
return Ok(Some(ModuleItem::AnnotatedMethod(data, body, MethodInjection::Add)));
}
_ => {}
(AnnotationKind::ReplaceGlobal, []) => {
let span = func.decl.span;
let name = ScopedName::top_level(func.decl.name.clone());
let entry = self
.repo
.globals()
.by_name(&name)
.exactly_one()
.map_err(|_| CompileError::UnresolvedFunction(name.name().into(), span))?;
let body = CompileBody::new(func, entry.index, env, true)
.ok_or(CompileError::Unsupported(Unsupported::AnnotatedFuncWithNoBody, span))?;
return Ok(Some(ModuleItem::Global(body)));
}
(AnnotationKind::If, [_]) => {
todo!("conditional compilation is not supported yet")
}
_ => {
return Err(CompileError::Unsupported(Unsupported::InvalidAnnotation, ann.span));
}
}
}

let name = ScopedName::new(func.decl.name.clone(), path.clone());
let index = self.repo.globals_mut().add(name, typ, flags);
let global = if let Ok(intrinsic) = Intrinsic::from_str(&func.decl.name) {
Expand All @@ -371,7 +390,40 @@ impl<'id> Compiler<'id> {
Ok(None)
}
}
SourceEntry::GlobalLet(_) => todo!(),
SourceEntry::GlobalLet(field) => {
let span = field.declaration.span;
let target = field
.declaration
.annotations
.iter()
.find(|ann| ann.kind == AnnotationKind::AddField)
.ok_or_else(|| CompileError::Unsupported(Unsupported::GlobalLetBinding, span))?;
let [Expr::Ident(ident, ident_span)] = &target.args[..] else {
return Err(CompileError::Unsupported(Unsupported::InvalidAnnotation, span));
};
let &id = types
.get(ident)
.ok_or_else(|| TypeError::UnresolvedType(ident.clone()))
.with_span(*ident_span)?;
let ct = self
.repo
.get_type_mut(id)
.unwrap()
.as_class_mut()
.ok_or_else(|| TypeError::UnresolvedType(ident.clone()))
.with_span(*ident_span)?;
let flags = get_field_flags(&field.declaration.qualifiers);
Self::validate_field(&mut self.reporter, ct.flags, flags, field.declaration.span);

let res = TypeEnv::new(types, &ScopedMap::default())
.resolve_type(&field.type_)
.with_span(field.declaration.span);
let Some(typ) = self.reporter.unwrap_err(res) else {
return Ok(None);
};
ct.fields.add(field.declaration.name, Field::new(typ, flags));
Ok(None)
}
}
}

Expand All @@ -394,10 +446,9 @@ impl<'id> Compiler<'id> {
}
}

fn validate_field(&mut self, type_flags: ClassFlags, field_flags: FieldFlags, span: Span) {
fn validate_field(reporter: &mut ErrorReporter<'id>, type_flags: ClassFlags, field_flags: FieldFlags, span: Span) {
if field_flags.is_native() && !type_flags.is_native() {
self.reporter
.report(CompileError::Unsupported(Unsupported::NativeInNonNative, span));
reporter.report(CompileError::Unsupported(Unsupported::NativeInNonNative, span));
}
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,8 @@ pub enum Unsupported {
NativeInNonNative,
#[error("function type with more than 8 parameters")]
FunctionMaxArityExceeded,
#[error("this kind of annotation")]
InvalidAnnotation,
#[error("introducing global let bindings")]
GlobalLetBinding,
}
14 changes: 13 additions & 1 deletion compiler/src/typer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,19 @@ impl<'ctx, 'id> Typer<'ctx, 'id> {
let body = self.typeck_seq(body, &mut locals.introduce_scope());
Ok((Expr::While(cond.into(), body, *span), InferType::VOID))
}
Expr::ForIn(_, _, _, _) => todo!(),
Expr::ForIn(elem, iter, body, span) => {
let (iter, iter_type) = self.typeck(iter, locals)?;
let elem_type = self.id_alloc.allocate_free_type();
iter_type
.constrain(&InferType::Mono(Mono::Data(Data::array(elem_type.clone()))), self.repo)
.with_span(*span)?;
let mut locals = locals.introduce_scope();
let info = self.id_alloc.allocate_local(elem_type);
let local = info.local;
locals.insert(elem.clone(), info);
let body = self.typeck_seq(body, &mut locals);
Ok((Expr::ForIn(local, iter.into(), body, *span), InferType::VOID))
}
Expr::BinOp(lhs, rhs, op, span) => {
let name = <&str>::from(op);
let matches = self
Expand Down

0 comments on commit e2caff2

Please sign in to comment.