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

Remove as_bool in Instruction trait #404

Merged
merged 6 commits into from
Dec 3, 2021
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
51 changes: 11 additions & 40 deletions src/instruction/binary_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//! That is `Add`, `Substract`, `Multiply` and `Divide`.

use crate::{
instruction::Operator,
instruction::{Operator, TypeId},
typechecker::{CheckedType, TypeCtx},
Context, ErrKind, Error, FromObjectInstance, InstrKind, Instruction, JkBool, JkFloat, JkInt,
Context, ErrKind, Error, FromObjectInstance, InstrKind, Instruction, JkFloat, JkInt,
ObjectInstance, TypeCheck, Value,
};

Expand Down Expand Up @@ -118,43 +118,6 @@ impl Instruction for BinaryOp {

Some(return_value)
}

fn as_bool(&self, ctx: &mut Context) -> Option<bool> {
// FIXME: Remove these
let l_value = self.execute_node(&*self.lhs, ctx)?;
let r_value = self.execute_node(&*self.rhs, ctx)?;

match &self.op {
Operator::Equals |
Operator::NotEquals |
Operator::Lt |
Operator::LtEq |
Operator::Gt |
Operator::GtEq => match l_value.ty() {
CheckedType::Resolved(ty) => match ty.id() {
"int" => {
Some(JkBool::from_instance(&JkInt::from_instance(&l_value)
.do_op(&JkInt::from_instance(&r_value), self.op)
.unwrap()).0)
}
"float" => {
Some(JkBool::from_instance(&JkFloat::from_instance(&l_value)
.do_op(&JkFloat::from_instance(&r_value), self.op)
.unwrap()).0)
}
_ => unreachable!(
"attempting as_bool operation with void type or unknown type AFTER typechecking"
),
}
_ => unreachable!(
"attempting binary operation with void type or unknown type AFTER typechecking"
),
}
_ => unreachable!(
"attempting as bool operation with non equality operator AFTER typechecking"
),
}
}
}

impl TypeCheck for BinaryOp {
Expand All @@ -172,7 +135,15 @@ impl TypeCheck for BinaryOp {
return CheckedType::Unknown;
}

l_type
match self.op {
Operator::Lt
| Operator::Gt
| Operator::LtEq
| Operator::GtEq
| Operator::Equals
| Operator::NotEquals => CheckedType::Resolved(TypeId::from("bool")),
_ => l_type,
}
Comment on lines +138 to +146
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be missing checking that both the l_type and r_type are the same? Maybe I'm missing part of the function, I can't check it for now. If that is the case, could you add a test case for this as it is a typechecking error to operate on two types with different types and I should have added one already :)

Copy link
Member Author

@Skallwar Skallwar Dec 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This done line 128. Don't know if this is tested though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, great thanks for checking!

}
}

Expand Down
2 changes: 0 additions & 2 deletions src/instruction/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use crate::{
pub struct Block {
instructions: Vec<Box<dyn Instruction>>,
is_statement: bool,
ty: CheckedType,
}

impl Block {
Expand All @@ -36,7 +35,6 @@ impl Block {
Block {
instructions: Vec::new(),
is_statement: true,
ty: CheckedType::Unknown,
}
}

Expand Down
18 changes: 2 additions & 16 deletions src/instruction/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
use crate::instruction::{FunctionDec, FunctionKind, Var};
use crate::typechecker::TypeCtx;
use crate::{
typechecker::CheckedType, Context, ErrKind, Error, FromObjectInstance, InstrKind, Instruction,
JkBool, ObjectInstance, TypeCheck,
typechecker::CheckedType, Context, ErrKind, Error, InstrKind, Instruction, ObjectInstance,
TypeCheck,
};
use std::rc::Rc;

Expand Down Expand Up @@ -186,20 +186,6 @@ impl Instruction for FunctionCall {

ret_val
}

fn as_bool(&self, ctx: &mut Context) -> Option<bool> {
self.execute(ctx).map(|instance| match instance.ty() {
CheckedType::Resolved(ty) => match ty.id() {
// FIXME:
"bool" => JkBool::from_instance(&instance).as_bool(ctx).unwrap(),
// We can safely unwrap since we checked the type of the variable
// FIXME: Is this correct?
_ => unreachable!(),
},
// FIXME: Is this correct?
_ => unreachable!(),
})
}
}

impl TypeCheck for FunctionCall {
Expand Down
19 changes: 15 additions & 4 deletions src/instruction/if_else.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
//! x = if condition { 12 } else { 13 };
//! ```

use crate::instruction::{Block, InstrKind, Instruction};
use crate::instance::FromObjectInstance;
use crate::instruction::{Block, InstrKind, Instruction, TypeId};
use crate::typechecker::TypeCtx;
use crate::value::JkBool;
use crate::{typechecker::CheckedType, Context, ObjectInstance, TypeCheck};
use crate::{ErrKind, Error};

Expand Down Expand Up @@ -61,10 +63,10 @@ impl Instruction for IfElse {
fn execute(&self, ctx: &mut Context) -> Option<ObjectInstance> {
ctx.debug_step("IF_ELSE ENTER");

let cond = self.condition.as_bool(ctx)?;
ctx.debug("COND", &cond.to_string());
let cond = self.condition.execute(ctx)?;
// ctx.debug("COND", &cond.to_string());

if cond {
if JkBool::from_instance(&cond).rust_value() {
Skallwar marked this conversation as resolved.
Show resolved Hide resolved
ctx.debug_step("IF ENTER");
self.if_body.execute(ctx)
} else {
Expand All @@ -81,6 +83,15 @@ impl Instruction for IfElse {

impl TypeCheck for IfElse {
fn resolve_type(&self, ctx: &mut TypeCtx) -> CheckedType {
let bool_checkedtype = CheckedType::Resolved(TypeId::from("bool"));
let cond_ty = self.condition.resolve_type(ctx);
if cond_ty != bool_checkedtype {
ctx.error(Error::new(ErrKind::TypeChecker).with_msg(format!(
"if condition should be a boolean, not a `{}`",
cond_ty
)));
}

let if_ty = self.if_body.resolve_type(ctx);
let else_ty = self
.else_body
Expand Down
3 changes: 2 additions & 1 deletion src/instruction/loop_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ impl Instruction for Loop {
},
LoopKind::While(cond) => {
ctx.debug_step("WHILE ENTER");
while cond.as_bool(ctx)? {
let cond = cond.execute(ctx)?;
while JkBool::from_instance(&cond).rust_value() {
self.block.execute(ctx)?;
}
ctx.debug_step("WHILE EXIT");
Expand Down
7 changes: 0 additions & 7 deletions src/instruction/method_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ impl Instruction for MethodCall {

call.execute(ctx)
}

fn as_bool(&self, ctx: &mut Context) -> Option<bool> {
let mut call = self.method.clone();
call.add_arg_front(self.var.clone());

call.as_bool(ctx)
}
}

impl TypeCheck for MethodCall {
Expand Down
12 changes: 0 additions & 12 deletions src/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,6 @@ pub trait Instruction: InstructionClone + Downcast + TypeCheck {
}
}

/// Maybe execute the instruction, transforming it in a Rust bool if possible. It is
/// only possible to execute as_bool on boolean variables, boolean constants, blocks
/// returning a boolean and functions returning a boolean.
fn as_bool(&self, ctx: &mut Context) -> Option<bool> {
ctx.error(
Error::new(ErrKind::Context)
.with_msg(format!("cannot be used as a boolean: {}", self.print())),
);

None
}

/// What is the type of the instruction: a Statement or an Expression.
/// This method will always return Expression(None) if the instruction is an
/// expression. This method does not care about the return value or the execution
Expand Down
39 changes: 1 addition & 38 deletions src/instruction/var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@

use crate::instruction::TypeDec;
use crate::typechecker::{CheckedType, TypeCtx};
use crate::{Context, ErrKind, Error, InstrKind, Instruction, JkBool, ObjectInstance, TypeCheck};
use crate::{Context, ErrKind, Error, InstrKind, Instruction, ObjectInstance, TypeCheck};

#[derive(Clone)]
pub struct Var {
name: String,
mutable: bool,
instance: ObjectInstance,
// FIXME: Maybe we can refactor this using the instance's type?
ty: CheckedType,
}

impl Var {
Expand All @@ -23,7 +21,6 @@ impl Var {
name,
mutable: false,
instance: ObjectInstance::empty(),
ty: CheckedType::Unknown,
}
}

Expand Down Expand Up @@ -71,40 +68,6 @@ impl Instruction for Var {
format!("{} = {}", base, self.instance.as_string())
}

fn as_bool(&self, ctx: &mut Context) -> Option<bool> {
use crate::FromObjectInstance;

// FIXME: Cleanup

match self.execute(ctx) {
Some(instance) => match instance.ty() {
CheckedType::Resolved(ty) => match ty.id() {
// FIXME:
"bool" => Some(JkBool::from_instance(&instance).as_bool(ctx).unwrap()),
// We can safely unwrap since we checked the type of the variable
_ => {
ctx.error(Error::new(ErrKind::Context).with_msg(format!(
"var {} cannot be interpreted as boolean",
self.name
)));
None
}
},
_ => todo!(
"If the type of the variable hasn't been determined yet,
typecheck it and call self.as_bool() again"
),
},
_ => {
ctx.error(Error::new(ErrKind::Context).with_msg(format!(
"var {} cannot be interpreted as boolean",
self.name
)));
None
}
}
}

fn execute(&self, ctx: &mut Context) -> Option<ObjectInstance> {
let var = match ctx.get_variable(self.name()) {
Some(v) => v,
Expand Down
11 changes: 0 additions & 11 deletions src/instruction/var_or_empty_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,6 @@ impl Instruction for VarOrEmptyType {
}
}
}

fn as_bool(&self, ctx: &mut Context) -> Option<bool> {
let symbol_type_id = TypeId::new(self.symbol.clone());
match ctx.get_type(&symbol_type_id) {
Some(_) => None,
None => {
let var_inst = Var::new(self.symbol.clone());
var_inst.as_bool(ctx)
}
}
}
}

impl TypeCheck for VarOrEmptyType {
Expand Down
4 changes: 0 additions & 4 deletions src/value/jk_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,6 @@ macro_rules! jk_primitive {
self.0.to_string()
}

fn as_bool(&self, _ctx: &mut Context) -> Option<bool> {
Some(self.0)
}

fn execute(&self, ctx: &mut Context) -> Option<ObjectInstance> {
ctx.debug("CONSTANT", &self.0.to_string());

Expand Down