Skip to content

Commit

Permalink
Add cat and indexing.
Browse files Browse the repository at this point in the history
  • Loading branch information
maloneymr committed May 3, 2024
1 parent c9af163 commit 7482d85
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 67 deletions.
6 changes: 3 additions & 3 deletions examples/sim.vir
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
public module Top {
incoming clock : Clock;
incoming in : Word[8];
outgoing out : Word[8];
outgoing out : Word[9];

reg r : Word[8] on clock;
r <= r->add(in);
out := r;
r <= r->add(1);
out := cat(r, 1w1);
}
12 changes: 11 additions & 1 deletion spec/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ For expressions which are well-typed, but whose type can't be inferred, you can
Types may have methods defined on them.
These vary according to the type.

### Concatenation

You concatenate words together using `cat(x, y)`.

### Indexing

You into words with `x[i]`.


## Grammar

Expand Down Expand Up @@ -158,11 +166,13 @@ Expr :=
ExprCall
ExprCall :=
"cat" "(" ExprList ")" |
ExprCall "->" Id "(" ExprList ")" |
ExprCall "->" "as" "(" Type ")" |
ExprIdx => e,
ExprIdx,
ExprIdx :=
ExprIdx "[" Nat "]" |
ExprBase
ExprBase :=
Expand Down
2 changes: 2 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub enum Expr {
Struct(Ident, Vec<(Field, Box<Expr>)>),
MethodCall(Box<Expr>, Ident, Vec<Expr>),
As(Box<Expr>, Type),
Idx(Box<Expr>, StaticIndex),
Cat(Vec<Expr>),
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down
17 changes: 0 additions & 17 deletions src/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ pub trait QueryGroup: salsa::Database {

fn moddef_hir_typed(&self, moddef: Ident) -> VirdantResult<hir::ModDef>;

fn moddef_entity_names(&self, moddef: Ident) -> Result<Vec<Ident>, VirdantError>;

fn moddef_component_names(&self, moddef: Ident) -> Result<Vec<Ident>, VirdantError>;

fn moddef_submodules(&self, moddef: Ident) -> Result<Vec<hir::Submodule>, VirdantError>;
Expand All @@ -36,8 +34,6 @@ pub trait QueryGroup: salsa::Database {

fn moddef_component(&self, moddef: Ident, component: Ident) -> Result<ast::Component, VirdantError>;

// fn moddef_entity_ast(&self, moddef: Ident, entity: Ident) -> Result<Vec<Ident>, VirdantError>;

fn moddef_component_type(&self, moddef: Ident, component: Ident) -> Result<ast::Type, VirdantError>;

fn moddef_component_connects(&self, moddef: Ident, component: Ident) -> Result<Vec<ast::InlineConnect>, VirdantError>;
Expand Down Expand Up @@ -361,19 +357,6 @@ fn moddef_component_names(db: &dyn QueryGroup, moddef: Ident) -> Result<Vec<Iden
Ok(result)
}

fn moddef_entity_names(db: &dyn QueryGroup, moddef: Ident) -> Result<Vec<Ident>, VirdantError> {
let moddef = db.moddef_ast(moddef)?;
let mut result = vec![];
for decl in moddef.decls {
match decl {
ast::Decl::Component(component) => result.push(component.name.clone()),
ast::Decl::Submodule(submodule) => result.push(submodule.name.clone()),
ast::Decl::Connect(_connect) => (),
}
}
Ok(result)
}

#[salsa::database(QueryGroupStorage)]
#[derive(Default)]
pub struct DatabaseStruct {
Expand Down
3 changes: 2 additions & 1 deletion src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub use std::sync::Arc;

pub type Width = u64;
pub type Field = String;
pub type StaticIndex = u64;

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Ident(String);
Expand Down Expand Up @@ -36,7 +37,7 @@ pub enum VirdantError {
pub enum TypeError {
TypeMismatch(),
CantInfer,
Other,
Unknown,
}

#[derive(Debug, Clone)]
Expand Down
16 changes: 8 additions & 8 deletions src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,11 @@ pub Expr: Box<Expr> = {
ExprCall: Box<Expr> = {
// <ll:@L> <name:Ctor> <rr:@R> => Box::new(Expr::Call(name, vec![], vec![])),
// <ll:@L> <name:Ctor> "(" <es:ExprList> ")" <rr:@R> => Box::new(Expr::Call(name, vec![], es)),
// "cat" "(" <es:ExprList> ")" => {
// Box::new(Expr::Cat(es))
// },

"cat" "(" <es:ExprList> ")" => {
Box::new(Expr::Cat(es))
},

// <ll:@L> <name:Id> "(" <es:ExprList> ")" <rr:@R> => {
// Box::new(Expr::FnCall(name, es))
// },
Expand All @@ -130,11 +132,9 @@ ExprCall: Box<Expr> = {
}

ExprIdx: Box<Expr> = {
/*
<ll:@L> <e:ExprIdx> "->" <field:Id> <rr:@R> => Box::new(Expr::IdxField(e, field.clone())),
<ll:@L> <e:ExprIdx> "[" <i:Nat> "]" <rr:@R> => Box::new(Expr::Idx(e, i)),
<ll:@L> <e:ExprIdx> "[" <j:Nat> ".." <i:Nat> "]" <rr:@R> => Box::new(Expr::IdxRange(e, j, i)),
*/
// <ll:@L> <e:ExprIdx> "->" <field:Id> <rr:@R> => Box::new(Expr::IdxField(e, field.clone())),
<e:ExprIdx> "[" <i:Nat> "]" => Box::new(Expr::Idx(e, i)),
// <ll:@L> <e:ExprIdx> "[" <j:Nat> ".." <i:Nat> "]" <rr:@R> => Box::new(Expr::IdxRange(e, j, i)),
<e:ExprBase> => e,
}

Expand Down
19 changes: 19 additions & 0 deletions src/hir/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ mod reference;
mod word;
mod vec;
mod methodcall;
mod idx;
mod cat;

use ascription::*;
use reference::*;
use word::*;
use vec::*;
use methodcall::*;
use idx::*;
use cat::*;

use std::collections::HashSet;

Expand Down Expand Up @@ -38,6 +42,8 @@ pub enum ExprNode {
Vec(ExprVec),
As(ExprAs),
MethodCall(ExprMethodCall),
Idx(ExprIdx),
Cat(ExprCat),
}

impl Expr {
Expand All @@ -48,6 +54,8 @@ impl Expr {
ExprNode::MethodCall(inner) => inner,
ExprNode::Vec(inner) => inner,
ExprNode::As(inner) => inner,
ExprNode::Idx(inner) => inner,
ExprNode::Cat(inner) => inner,
}
}
}
Expand Down Expand Up @@ -125,6 +133,17 @@ impl Expr {
let subject_hir: Expr = Expr::from_ast(subject);
ExprNode::As(ExprAs(subject_hir, Type::from_ast(typ)))
},
ast::Expr::Idx(subject, idx) => {
let subject_hir: Expr = Expr::from_ast(subject);
ExprNode::Idx(ExprIdx(subject_hir, *idx))
},
ast::Expr::Cat(es) => {
let mut es_hir = vec![];
for e in es {
es_hir.push(Expr::from_ast(e));
}
ExprNode::Cat(ExprCat(es_hir))
},
_ => todo!(),
};
expr_node.without_type()
Expand Down
60 changes: 60 additions & 0 deletions src/hir/expr/cat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::common::*;
use super::*;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExprCat(pub Vec<Expr>);

impl IsExpr for ExprCat {
fn subexprs(&self) -> Vec<Expr> {
self.0.clone()
}

fn typeinfer(&self, ctx: Context<Path, Arc<Type>>) -> Result<Expr, TypeError> {
let mut args = vec![];
let mut w = 0u64;
for e in &self.0 {
let arg: Expr = e.typeinfer(ctx.clone())?;
let arg_typ: Arc<Type> = arg.type_of().unwrap();
args.push(arg);
if let Type::Word(m) = arg_typ.as_ref() {
w += m;
} else {
return Err(TypeError::Unknown);
}
}
let typ: Arc<Type> = Type::Word(w).into();
Ok(ExprNode::Cat(ExprCat(args)).with_type(typ))
}

/*
let typed_args: Vec<Expr> = self.0.iter().map(|arg| arg.typeinfer(ctx.clone()).unwrap()).collect();
let element_type = typed_args[0].type_of().unwrap();
for typed_arg in &typed_args {
if typed_arg.type_of().unwrap() != element_type {
return Err(TypeError::Unknown);
}
}
let typ: Arc<Type> = Type::Vec(element_type, self.0.len()).into();
Ok(ExprNode::Vec(ExprVec(typed_args)).with_type(typ))
*/

fn eval(&self, ctx: Context<Path, Value>, typ: Arc<Type>) -> Value {
let mut cat_width: u64 = 0;
let mut cat_val: u64 = 0;
let values = self.0.iter().map(|e| e.eval(ctx.clone()));
dbg!(&typ);
dbg!(&values);

for v in values.rev() {
if let Value::Word(width, val) = v {
cat_val |= val << cat_width;
cat_width += width;
} else {
return Value::X(typ.clone());
}
}

Value::Word(cat_width, cat_val)
}
}

52 changes: 52 additions & 0 deletions src/hir/expr/idx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::common::*;
use super::*;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExprIdx(pub Expr, pub StaticIndex);

impl ExprIdx {
fn subject(&self) -> Expr {
self.0.clone()
}

fn index(&self) -> StaticIndex {
self.1
}
}

impl IsExpr for ExprIdx {
fn subexprs(&self) -> Vec<Expr> {
vec![self.0.clone()]
}

fn typeinfer(&self, ctx: Context<Path, Arc<Type>>) -> Result<Expr, TypeError> {
let typed_subject: Expr = self.subject().typeinfer(ctx.clone())?;
let subject_type: Arc<Type> = typed_subject.type_of().unwrap();
if let Type::Word(n) = subject_type.as_ref() {
if self.index() < *n {
let typ: Arc<Type> = Type::Word(1).into();
Ok(ExprNode::Idx(ExprIdx(typed_subject, self.index())).with_type(typ))
} else {
Err(TypeError::Unknown)
}
} else {
Err(TypeError::Unknown)
}
}

fn eval(&self, ctx: Context<Path, Value>, typ: Arc<Type>) -> Value {
let subject_value = self.subject().eval(ctx);
if let Value::Word(_width, v) = subject_value {
// v_index_masked should be 0b00..000100..00
// eg, 1 in position self.index(), or else all zeroes
let v_index_masked = v & (1 << self.index());
// v_new should be 0b000.....01
// eg, 1 in index 0, or else all zeroes
let v_new = v_index_masked >> self.index();
assert!(v_new == 0 || v_new == 1);
Value::Word(1, v_new)
} else {
Value::X(typ.clone())
}
}
}
2 changes: 1 addition & 1 deletion src/hir/expr/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl IsExpr for ExprVec {
let element_type = typed_args[0].type_of().unwrap();
for typed_arg in &typed_args {
if typed_arg.type_of().unwrap() != element_type {
return Err(TypeError::Other);
return Err(TypeError::Unknown);
}
}
let typ: Arc<Type> = Type::Vec(element_type, self.0.len()).into();
Expand Down
4 changes: 2 additions & 2 deletions src/hir/expr/word.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ impl IsExpr for ExprWord {
let typ = Arc::new(Type::Word(*expected_width));
Ok(ExprNode::Word(ExprWord(self.value(), Some(*expected_width))).with_type(typ))
},
(Type::Word(_expected_width), None) => Err(TypeError::Other),
(_, _) => Err(TypeError::Other),
(Type::Word(_expected_width), None) => Err(TypeError::Unknown),
(_, _) => Err(TypeError::Unknown),
}
}

Expand Down
Loading

0 comments on commit 7482d85

Please sign in to comment.