~mikelma/oktac

9671455b3b4bc9ab84ed639bb2fb27e197055da2 — mikelma 5 months ago 3d9e536
rust-like explicit typing for numbers
M CHANGELOG.md => CHANGELOG.md +1 -0
@@ 10,6 10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- Functions as first-class citizens.
- Add `-L` cli argument for including paths to okta libraries.
- Rust-like explicit typing for numbers ([#9](https://todo.sr.ht/~mikelma/oktac/9)).

### Added


M docs/reference.md => docs/reference.md +3 -0
@@ 48,6 48,8 @@ let a = 10;

# this behavior can be avoided by manually defining the type of the variable
let b: u8 = 10;
# the type of a number can be also splicitly set in the number itself 
let b = 10u8;

# in this case, the type of `c` can be inferred from the right-hand side expression
let c = b + 7;


@@ 55,6 57,7 @@ let c = b + 7;
# the same happens with floats:
let x = 4.2;      # the type of `x` defaults to `f64`
let y: f32 = 4.2; # override the default type by manually defining the type
let y = 4.2f32;   # this line and the one above produce the same effect  
let z = y - 1.0;  # here the type of `z` can be inferred: `f32`
```


M examples/brain-fuck/main.ok => examples/brain-fuck/main.ok +3 -3
@@ 4,9 4,9 @@ fun main(): i8 {
    let program = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.";
    let input = "";

    let program_idx: u64 = 0;
    let tape_idx:    u64 = 0;
    let input_idx:   u64 = 0;
    let program_idx = 0u64;
    let tape_idx    = 0u64;
    let input_idx   = 0u64;

    let tape: [u8; 20] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];


M examples/game-of-life/main.ok => examples/game-of-life/main.ok +5 -5
@@ 50,7 50,7 @@ fun gen_world(): [i8] {
}

fun count_neighbours(world: &[i8], i: u64, j: u64): i8 {
    let count: i8 = 0;
    let count = 0i8;

    # upper neighbor
    if i > 0 {


@@ 119,16 119,16 @@ fun print_world(world: &[i8]) {
}

fun random_init(world: &[i8]) {
    for let i:u64=0; i<WORLD_SIZE; i=i+1 {
        for let j:u64=0; j<WORLD_SIZE; j=j+1 {
    for let i=0u64; i<WORLD_SIZE; i=i+1 {
        for let j=0u64; j<WORLD_SIZE; j=j+1 {
            *world[i*WORLD_SIZE+j] = rand() & 1;
        }
    }
}

fun copy_world(from: &[i8], to: &[i8]) {
    for let i:u64=0; i<WORLD_SIZE; i=i+1 {
        for let j:u64=0; j<WORLD_SIZE; j=j+1 {
    for let i=0u64; i<WORLD_SIZE; i=i+1 {
        for let j=0u64; j<WORLD_SIZE; j=j+1 {
            set_cell(to, i, j, get_cell(from, i, j));
        }
    }

M examples/overview/main.ok => examples/overview/main.ok +3 -2
@@ 21,12 21,13 @@ const MEANING_OF_LIFE: i64 = PRETTY_NUM + 10
const PRETTY_NUM: i64 = 32

fun main(): i64 {
    let val = 11i32;

    let test = Test { 
        a = MEANING_OF_LIFE, 
        list = [ 
            TestInner { value = 10 }, 
            TestInner { value = 11 } 
            TestInner { value = 10  }, 
            TestInner { value = val } 
        ],
    };


M src/ast/check.rs => src/ast/check.rs +2 -1
@@ 540,8 540,9 @@ pub fn get_node_type_no_autoconv(node: &AstNode) -> Result<VarType, LogMesg> {
        AstNode::Int16(_) => Ok(VarType::Int16),
        AstNode::UInt16(_) => Ok(VarType::UInt16),
        AstNode::Int32(_) => Ok(VarType::Int32),
        AstNode::Int64(_) => Ok(VarType::Int64),
        AstNode::UInt32(_) => Ok(VarType::UInt32),
        AstNode::Int64(_) => Ok(VarType::Int64),
        AstNode::UInt64(_) => Ok(VarType::UInt64),
        AstNode::Float32(_) => Ok(VarType::Float32),
        AstNode::Float64(_) => Ok(VarType::Float64),
        AstNode::Boolean(_) => Ok(VarType::Boolean),

M src/ast/expr.rs => src/ast/expr.rs +36 -7
@@ 277,10 277,42 @@ pub fn parse_parameters(pair: Pair<Rule>, builtin_fn: bool) -> Result<Vec<AstNod
}

pub fn parse_value(pair: Pair<Rule>) -> AstNode {
    let value = pair.clone().into_inner().next().unwrap();
    let pair_str = pair.as_str();
    let pair_loc = pair.as_span().start_pos().line_col().0;
    let value = pair.into_inner().next().unwrap();
    match value.as_rule() {
        Rule::number => AstNode::Int64(value.as_str().parse().unwrap()),
        Rule::float => AstNode::Float64(value.as_str().parse().unwrap()),
        Rule::number => {
            let mut inner = value.into_inner();
            let num_part = inner.next().unwrap().as_str();
            if let Some(ty_part) = inner.next() {
                match ty::parse_simple_ty(ty_part).unwrap() {
                    VarType::Int8 => AstNode::Int8(num_part.parse().unwrap()),
                    VarType::UInt8 => AstNode::UInt8(num_part.parse().unwrap()),
                    VarType::Int16 => AstNode::Int16(num_part.parse().unwrap()),
                    VarType::UInt16 => AstNode::UInt16(num_part.parse().unwrap()),
                    VarType::Int32 => AstNode::Int32(num_part.parse().unwrap()),
                    VarType::UInt32 => AstNode::UInt32(num_part.parse().unwrap()),
                    VarType::Int64 => AstNode::Int64(num_part.parse().unwrap()),
                    VarType::UInt64 => AstNode::UInt64(num_part.parse().unwrap()),
                    _ => unreachable!(),
                }
            } else {
                AstNode::Int64(num_part.parse().unwrap())
            }
        }
        Rule::float => {
            let mut inner = value.into_inner();
            let float_part = inner.next().unwrap().as_str();
            if let Some(ty_part) = inner.next() {
                match ty::parse_simple_ty(ty_part).unwrap() {
                    VarType::Float64 => AstNode::Float64(float_part.parse().unwrap()),
                    VarType::Float32 => AstNode::Float32(float_part.parse().unwrap()),
                    _ => unreachable!(),
                }
            } else {
                AstNode::Float64(float_part.parse().unwrap())
            }
        }
        Rule::id => AstNode::Identifier(value.as_str().to_string()),
        Rule::boolean => AstNode::Boolean(value.as_str().parse().unwrap()),
        Rule::array => {


@@ 302,10 334,7 @@ pub fn parse_value(pair: Pair<Rule>) -> AstNode {
                match check::node_type(values[0].clone(), None).1 {
                    Ok(t) => t,
                    Err(e) => {
                        e.lines(pair.as_str())
                            .location(pair.as_span().start_pos().line_col().0)
                            .send()
                            .unwrap();
                        e.lines(pair_str).location(pair_loc).send().unwrap();
                        VarType::Unknown
                    }
                }

M src/grammar.pest => src/grammar.pest +9 -5
@@ 142,13 142,16 @@ rangeVal = { expr? }

value = { float | number | str | array | enm | strct | boolean | id }

number   = @{ ("-")? ~ ASCII_DIGIT+ }
float    = @{ ("-")? ~ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }
number = ${ numPart ~ intType? }
    numPart = @{ ("-")? ~ ASCII_DIGIT+ }
float = ${ floatPart ~ floatType? }
    floatPart = @{ ("-")? ~ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }

boolean  = { "true" | "false" }
id       = @{ (!reserved | &(reserved~(ASCII_ALPHANUMERIC| "_"))) ~ "_"* ~ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_" )* }
array    = { "[" ~ "]" |
             "[" ~ expr ~ ("," ~ expr)* ~ "]"
} 
boolean  = { "true" | "false" }

strct = { id ~ structMembers }
    memberDecl = { id ~ "=" ~ expr } 


@@ 206,8 209,9 @@ shiftLeft  = { "<<" }
shiftRight = { ">>" }
modulo     = { "%" }

reserved = { intTypes | ("f32" | "f64") | "c_voidptr" | "str" | keywords}
    intTypes = @{ ("i" | "u") ~ ("8" | "16" | "32" | "64") }
reserved = { intType | floatType | "c_voidptr" | "str" | keywords}
    intType = @{ ("i" | "u") ~ ("8" | "16" | "32" | "64") }
    floatType = @{ "f" ~ ("32" | "64") }
    keywords = { "if" | "while" | "loop" | "for" | "fun" 
                 | "struct" | "enum" | "use" | "break" | "ret" 
                 | "type" | "const" | "macro"