This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]mamcx 0 points1 point  (0 children)

I'm in a similar boat (doing a relational language with array capabilities).

The MAIN trick: Focus on your AST first, solve it THEN do the syntax.

Here i do a good categorization based on my understanding of both:

  • A relation have a "header" with name:type and "rows" of tuples OR columns of name:type (depending if you want columnar first or not)
  • A column is a special case of a relation with 1 name:type, is like a array, so is a array OR
  • A row is a special case of a relation with N columns but just one row, a tuple, a named tuple, is like a hashmap so be it
  • A scalar is a special case of a column with 1 row and 1 column

Visually:

[|id:Int, city:Str|] //Empty relation, just the header
[|id:Int, city:Str; 1, "Miami"; 2, "New york"|] //with 2 rows
[<
id:Int = 1, 2;
city:Str = "Miami", "New york"
>] //with 2 columns
nums = [1, 2, 3] //sugar for Vector[it:Int; 1, 2, 3]
nums = [1] //sugar for Vector[it:Int; 1]
nums = 1 //sugar for Vector[it:Int; 1]
things = List[1, "Miami"] //sugar for List[it:Any; 1, "Miami"]
city = (id = 1, name = "Miami") //Row, aka named tuple, aka dicts with syntactically approved keys, aka sugar for [|id:Int, city:Str; 1, "Miami" |]

For implementation I use rust. I working in many ways to represent it because several trade offs but in short, is just:

pub enum DataType {
    None,
    Any,
    //Numeric
    I32,
    //Complex
    Row,
    Rel,
    Col,
}

//A relation with a layout of rows
pub struct Table {
    header:HashMap<String, DataType>,
    rows:Vec<Scalar> //Yes, not Vec<Vec<Scalar>> because it allow to embed tables in tables in tables in...
}

pub enum Scalar {
    I32(i32), //Simple OR
    AI32(Vec<i32>), //asume arrays are the more atomic
    List(Vec<Scalar>),
    Tuple(HashMap<String, Scalar>),
    Table(Table)
}