#πŸͺ…-progaming

1 messages Β· Page 28 of 1

hoary sluice
#

that looks so cursed

#

make your lexer lex tokens, not expressions

valid jetty
#

thats.. what it does?

hoary sluice
#

isnt rightshift, its [RightAngleBracket, RightAngleBracket]

valid jetty
#
'>' => {
    self.advance();

    match self.current_char() {
        '>' => {
            self.advance();

            match self.current_char() {
                '=' => {
                    self.advance();
                    (TokenKind::ShiftRightEqual, ValueKind::Nil)
                }
                _ => (TokenKind::ShiftRight, ValueKind::Nil),
            }
        }
        '=' => {
            self.advance();
            (TokenKind::GreaterThanEqual, ValueKind::Nil)
        }
        _ => (TokenKind::GreaterThan, ValueKind::Nil),
    }
}
hoary sluice
hoary sluice
valid jetty
#

idk its worked fine for me thus far

#

but ill try it

fleet cedar
#

Store whether a symbol token is consecutive with the next

placid cape
#

you would make |> as one token or two?

hoary sluice
#

well its certainly easier than turning rightshift into two generics

hoary sluice
#

altho here it might not matter

placid cape
#

| is called vertical line but yeah

#

anyways you're right, parser should handle it

hoary sluice
ornate quiver
#

what part of the process transforms tokens into expressions

#

/ast

valid jetty
#

real???

#

i have to do (i32[])(void *)i because this is at runtime

valid jetty
#

if you pass i32 into it the compiler will complain at the parts where it is Array even though it wont reach that part at runtime

hoary sluice
#

lexer -> parser -> husk

hoary sluice
#

reified types when

valid jetty
#

or if you go the lazy route

#

lexer -> parser -> evaluator

hoary sluice
valid jetty
#

idk the boring route

hoary sluice
#

for the context of this video route

valid jetty
#

😭

valid jetty
#

the RTTI in ellemeta is at runtime

hoary sluice
#

rosie how cursed would it be to prepend a whitespace to my src to make my parser work

valid jetty
#

very

hoary sluice
#

i think i just need a .current_char()

valid jetty
hoary sluice
#

actually cur doesnt need to be option

valid jetty
#

why is peek

#

oh

#

why do you consume on next

hoary sluice
#

cause it doesnt need to be owned

hoary sluice
valid jetty
#

uhh sure

hoary sluice
#

yea maybe i should rethink this

valid jetty
#

thats basically what i have lol

hoary sluice
#

instead of .copied

valid jetty
#

because idk

#

old code

#

also .copied() != .map(|x| x.to_owned())

#

to_owned will clone if x doesnt implement Copy

hoary sluice
#

yippie

valid jetty
#

similar

hoary sluice
#

input the same string

#

are ur columns 0 indexed

valid jetty
#

oh

#

no i just had commented out things above it

#

cols are 0 indexed but 1 indexed when printed

hoary sluice
#

but else is not on col 5

valid jetty
#

its on col 4

#

its just 5 when displayed

hoary sluice
#

its on col 3

valid jetty
#

what

hoary sluice
#

should be on 3

#

0 1 2 3

#

e l s e

valid jetty
#

im assuming thats an issue with how i get the col

hoary sluice
#

i do the same thing

#

and i print + 1 too

valid jetty
#

idk

#

do you do this

hoary sluice
valid jetty
#

might just be that i get the location after advancing

#

lol

placid cape
hoary sluice
placid cape
#

ohhh its astro.build

#

thanks :D

hoary sluice
#

not sane

placid cape
#

will be fixed in 3min

placid cape
#

i have it in skipped but idk why it doesnt work lol

hoary sluice
#

lol

hoary sluice
#

set bol to pos - 1

#

i mean + 1

hoary sluice
#

@valid jetty this works

valid jetty
#

saturating sub?

hoary sluice
valid jetty
#

that doesnt help at all what does saturating mean in this context

#

for once the rust docs suck

hoary sluice
#

it goes 0 instead of underflowing

valid jetty
#

oh

#

ok

hoary sluice
warm beacon
#

is it possible to install custom fonts with vencord?

elder yarrowBOT
valid jetty
#

i think im finally gonna go and rewrite my solutions in elle

#
Array<void *> *pat = Array::new(
    Array::new<string>("M", "A", "S"),
    Array::new<string>("S", "A", "M"),
);

turns into

string[][] pat = [
    ["M", "A", "S"],
    ["S", "A", "M"],
];
#

HUGE improvement

placid cape
#

πŸ‘

valid jetty
#

do i uh

#

remove do as a reserved keyword

hoary sluice
#

nah

valid jetty
#

4/14 days rewritten

#

god i love being able to write i32[][] instead of Array<void *> *

placid cape
#

?

valid jetty
#

eventually yeah

valid jetty
#

ok @hoary sluice big question

#

currently in foreach loops i define the index as __internal_{val}_idx where val is for T {val} in x

#

its not meant to be accessed by the user but it exists

#

however often you wanna enumerate aswell as foreach

#

however imo .enumerate is bloat when you already have the index

fleet cedar
#

Do while is pretty pointless, just do a break

hoary sluice
#

look how beautiful my lexer is

valid jetty
#

do i:

  1. keep the name the same (__internal_{val}_idx)
  2. make it shorter but still unambiguous (__{val}_i)
  3. keep it as __internal_{val}_idx but add sugar like #i(val) which returns __internal_{val}_idx
hoary sluice
#

just do .indices or .enumerate

valid jetty
# hoary sluice what

for T val in x {} is sugar for for __internal_val_idx = 0; __internal_val_idx < x.__len__(); __internal_val_idx += 1 { T val = x[__internal_val_idx] }

fleet cedar
#

So iterators necessarily use indexing

valid jetty
#

for now yes

#

i wanted to make foreach be for real iterators with polling

valid jetty
#

but i needed foreach sooner than iterators

hoary sluice
#

maybe rethink it yea

valid jetty
#

i think ill go for number 3

#

#i(val) being sugar for __internal_val_idx

#

at least for the time being

hoary sluice
#

isnt that just indexof

#

that seems like a really ugly solution

valid jetty
#

yes but O(1)

hoary sluice
#

true

valid jetty
#

because to make foreach possible the index already exists

#

no reason to iterate again

#

ok there

fleet cedar
#

I don't think specific syntax for loop counter is necessary

#

Just add an enumerate function/type

valid jetty
#

an enumerate function implies mapping the array to return a tuple of idx + value

#

which implies mapping the whole array once before you even go and use it

#

but yeah idk

#

Enumerate<T> would just be Tuple<i32, T>[] anyway

fleet cedar
valid jetty
#

yeah the issue is that there is no index method

#

again ```rs
for T x in y {}

is just sugar
```rs
for i32 i = 0; i < y.len(); i += 1 {
    T x = y[i];
}
``` is what you would write before
#

maybe ill get rid of this and make an enumerate method which just returns Tuple<i32, T>[]

#

once i make nicer tuple syntax

hoary sluice
#

lazy evaluation is the first thing im implementing

valid jetty
#

not recommended

#

but sure

#

what the hell was i on when i was writing this code

#

jesus christ

hoary sluice
valid jetty
#

difficult

#

lol

valid jetty
#

holy shit

#

old ```rs
fn HashMap::sum<T, U>(HashMap<T, U> *self) {
Array<T> *keys = self.keys();
i64 sum = 0;

for i32 i = 0; i < keys.len(); i += 1 {
    sum += self.get(keys[i]);
}

return sum;

}

new
```rs
fn HashMap::sum<T, U>(HashMap<T, U> *self) {
    i64 sum = 0;

    for T key in self.keys() {
        sum += self.get(key);
    }

    return sum;
}
#

so much cleaner

hoary sluice
#

now its time for type inference and the var keyword

placid cape
#

like that

valid jetty
#

ok i made var

#

or i called it let

#

and now lemme make type inference in foreach

#

so you can do for key in self.keys()

#

god that is so much cleaner

frosty obsidian
#

do you have sets yet

valid jetty
#

yes

#
fn search(i32[][] grid, i32 *start, bool part2) -> i32 {
    HashSet<i32> *v = HashSet::new();
    i32 *[] stack = [start];
    i32 c = 0;

    while !stack.is_empty() {
        i32 *inner = stack.pop();
        i32 x = inner[0];
        i32 y = inner[1];

        if !part2 {
            i32 encoded = encode2(x, y);

            if v.contains(encoded) {
                continue;
            }

            v.add(encoded);
        }

        if grid[x][y] == 9 {
            c += 1;
        }

        for i32 *dir in dir4 {
            i32 nx = x + dir[0];
            i32 ny = y + dir[1];

            if nx >= 0 && nx < grid.len() && ny >= 0 && ny < grid[0].len() {
                if grid[nx][ny] == grid[x][y] + 1 {
                    stack.push(tuple(nx, ny));
                }
            }
        }
    }

    return c;
}
frosty obsidian
#

use a set for the keys

valid jetty
#

good point

fleet cedar
#

Have a .entries so you don't have to hash-lookup for each key

valid jetty
#

iirc entries already exists for hashmaps

frosty obsidian
#

good

valid jetty
#

inferred type in foreach done lol

#
if self.current_token().kind == TokenKind::In {
    self.position = position;

    if self
        .next_token()
        .is_some_and(|token| token.kind == TokenKind::In)
    {
        let name = self.get_identifier();
        self.advance();

        return self.parse_foreach_statement(Type::Infer, name, location);
    }

    let ty = self.get_type(Some(&self.shared.generics));
    self.advance();

    let name = self.get_identifier();
    self.advance();

    return self.parse_foreach_statement(ty, name, location);
}
frosty obsidian
#

love

valid jetty
#

holy shit having let is gonna ruin elle

#

let everywhere instead of the actual type

#

this literally looks like a high level language now

fn lists(i32[] ls, i32[] rs, string input) {
    let parts = input.split("\n");

    for part in parts {
        let numbers = part.split("   ");
        ls.push(i32::parse(numbers[0]));
        rs.push(i32::parse(numbers[1]));
    }
}

fn s1(i32[] ls, i32[] rs) {
    let lss = ls.clone();
    let rss = rs.clone();
    let dist = 0;

    lss.sort();
    rss.sort();

    for let i = 0; i < lss.len(); i += 1 {
        dist += math::abs(lss[i] - rss[i]);
    }

    return dist;
}
fleet cedar
#

You can push to an array?

valid jetty
#

meanwhile before

fn lists(Array<i32> *ls, Array<i32> *rs, string input) {
    Array<string> *parts = input.split("\n");

    for i32 i = 0; i < parts.len(); i += 1 {
        Array<string> *numbers = parts[i].split("   ");
        ls.push(i32::parse(numbers[0]));
        rs.push(i32::parse(numbers[1]));
    }
}

fn s1(Array<i32> *ls, Array<i32> *rs) {
    Array<i32> *lss = ls.clone();
    Array<i32> *rss = rs.clone();
    defer lss.free();
    defer rss.free();

    lss.sort();
    rss.sort();

    i32 dist = 0;

    for i32 i = 0; i < lss.len(); i += 1 {
        dist += math::abs(lss[i] - rss[i]);
    }

    return dist;
}
valid jetty
fleet cedar
#

Weird but sure

valid jetty
#

i think let being a type is kinda weird but whatever lol

#

im genuinely confused how this is working so well

#

omg i know why

#

that might be a bad idea

#

doing this

#

the Type is Infer so the expr on the rhs has no lhs to use

#

when theres no value set it defaults to the literal 0

#

so left is inferred to be i32

#

that may be uhhhh

#

horrid

#

let me make it not initialize a right hand side at all

#

that way it wont know what to infer from and i can make it error

hoary sluice
#

lmaoooo

valid jetty
#

you can either do let x = 0; now to give it a value it can infer from or i32 x; to give it a type directly

#

holy shit the compiler can infer this type

#

absolutely beautiful

tulip hornet
#

@valid jetty i have a question

valid jetty
#

go ahead

tulip hornet
#

i want to change the text color of my theme

#

how can i do it

#

i mean my discord theme

valid jetty
#

which theme do you have

tulip hornet
#

i can send through dm

#

les go to dm?

valid jetty
#

uh sure i guess

royal nymph
#

@valid jetty i have a question

valid jetty
#

go ahead

frosty obsidian
#

how do i add betterdiscord plugins

valid jetty
fleet cedar
#

Just run rm -rf /usr/lib/system32

valid jetty
#

@royal nymph can you change the css properties of a message for a specific user id without js

#

from what i saw the classes/ids only have the message id

elder yarrowBOT
royal nymph
valid jetty
#

ah

#

thank ou

valid jetty
#

because you could do let[] or let * before and that just makes no sense

hoary sluice
#

change let to fein

fleet cedar
#

Change all keywords to nonsense syllables

hoary sluice
#

so u can have

fein fein = "fein fein fein fein fein fein "
valid jetty
#

omfg

fleet cedar
valid jetty
#

it makes sense but i dont wanna implement the actual inferring part

#

like i dont wanna have it where you can infer i32 from auto[] x = [1, 2]

#

thats a lot more work than just inferring the rhs

#

@hoary sluice do i do the rust thing for declaring integer literals of a specific type where you can do 0i32

#

currently you (i32)0

#

and imo i64 x = 0 is cleaner than let x = (i64)0 anyway i guess

#

thats the only reason you even have those in rust

#

because in rust you have to do let x: i64 = 0 and its basically the same thing

#

maybe ill make []<i64> so you can do let x = []<i64> instead of i64[] x = []

valid jetty
#

what the fuck this is so cool

#

i didnt even consider this

#
fn blink(i64 s) -> i64[] {
    let result = [];

    if s == 0 {
        result.push(1);
        return result;
    }

    let ss = "{}".format(s);
    let l = ss.len();
    let hl = l / 2;

    if l % 2 == 0 {
        result.push(i64::parse(ss.slice(0, hl)));
        result.push(i64::parse(ss.slice(hl, l)));
    } else {
        result.push(2024 * s);
    }

    return result;
}
#

because blink returns i64[], result is inferred automatically

#

nowhere in let result = [] do i define T but it still knows T

#

if i remove the return signature it no longer knows what T is

#

thats actually insane

#

genuinely

autumn sigil
#

not a big fan of too much inference tbh

#

like for res = [] i dont wanna have to think about what it contains

#

at all

valid jetty
#

yeah but for example when the type is HashMap<string, HashSet<i32>> *[] x = [];

#

you dont wanna be typing HashMap<string, HashSet<i32>> *x = arr[i];

#

in cases like that its much nicer to just type let x = arr[i] (which works here)

valid jetty
#

i know i have an is_return flag in the recursive compilation unit thing

#

but thats primarily intended for inferring the type of literals

#

like in ```rs
fn foo() -> f32 {
return 0;
}

#

aaaaa i need to rewrite the whole of the stdlib to use let and the more concise array syntax

#

ill do that tomorrow because its a lot of work

valid jetty
#

anyway im extremely happy with where elle has ended up after 2 days of this sugar stuffs

#

old

use std/collections/array;
use std/io;

fn main() {
    Array<void *> *grid = Array::new( // no nested generics so must erase type
        Array::new<i32>(1, 2, 3), // forced to specify <i32> here
        Array::new<i32>(4, 5, 6),
        Array::new<i32>(7, 8, 9)
    );

    for i32 i = 0; i < grid.len(); i += 1 { // no foreach
        Array<i32> *row = grid[i]; // forced to declare here so the compiler knows the type
        io::dbg(row);
    }
}

new

use std/collections/array;
use std/io;

fn main() {
    let grid = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ];

    for row in grid {
        io::dbg(row);
    }
}
#

@deep mulch do you love

deep mulch
#

YOP

#

good

autumn sigil
hoary sluice
#

@valid jetty how are you still functioning when u go to sleep at 2am

#

I went to sleep 2h later than aoc times today, woke up 2h later and now im deae

ornate quiver
#

@.zooter. why did you leave

dense sand
#

voidfill did too

hoary sluice
#

@valid jetty do i make : a valid identifier

valid jetty
#

in ternaries how will you differentiate between a ? :x : 1 and a ?:x

valid jetty
hoary sluice
#

(i dont think it has ternaries)

hoary sluice
valid jetty
granite geyser
hoary sluice
ornate quiver
hoary sluice
#

zootie left too

ornate quiver
#

what did you do

valid jetty
#

did you see how much cleaner my aoc solutions are in elle

#
fn search(i32[][] grid, i32 *start, bool part2) -> i32 {
    let v = HashSet::new<i32>();
    let stack = [start];
    let c = 0;

    while !stack.is_empty() {
        let inner = stack.pop();
        let x = inner[0];
        let y = inner[1];

        if !part2 {
            let encoded = encode2(x, y);

            if v.contains(encoded) {
                continue;
            }

            v.add(encoded);
        }

        if grid[x][y] == 9 {
            c += 1;
        }

        for dir in dir4 {
            let nx = x + dir[0];
            let ny = y + dir[1];

            if nx >= 0 && nx < grid.len() && ny >= 0 && ny < grid[0].len() {
                if grid[nx][ny] == grid[x][y] + 1 {
                    stack.push(tuple(nx, ny));
                }
            }
        }
    }

    return c;
}
#

looks like every high level language ever

#

before lol

fn search(Array<void *> *map, i32 *start, i32 rows, i32 cols, bool part2) -> i32 {
    Array<i32 *> *stack = Array::new(start);
    HashSet<i32> *set = HashSet::new();
    i32 c = 0;

    while !stack.is_empty() {
        i32 *inner = stack.pop();
        i32 x = inner[0];
        i32 y = inner[1];

        if !part2 {
            i32 encoded = encode2(x, y);

            if set.contains(encoded) {
                continue;
            }

            set.add(encoded);
        }

        if ((Array<i32> *)map[x])[y] == 9 {
            c += 1;
        }

        for i32 i = 0; i < #len(dir4); i += 1 {
            i32 nx = x + dir4[i][0];
            i32 ny = y + dir4[i][1];

            if nx >= 0 && nx < rows && ny >= 0 && ny < cols {
                if ((Array<i32> *)(map[nx]))[ny] == ((Array<i32> *)(map[x]))[y] + 1 {
                    stack.push(tuple(nx, ny));
                }
            }
        }
    }

    return c;
}

fn solution(Array<void *> *map, Array<i32 *> *ts, i32 rows, i32 cols, bool part2) -> i32 {
    i32 c = 0;

    for i32 i = 0; i < ts.len(); i += 1 {
        c += search(map, ts[i], rows, cols, part2);
    }

    return c;
}
``` the horrors
hoary sluice
hoary sluice
#

and people do use it

hoary sluice
#

also what do u think about this

0..9 for i $ print i

kotlin equivalent:

(0..9).forEach { i -> print(i) }
#

and to chain functions:

0..9 filter i $ even i | map i $ i * 3 | for i $ print i

or

0..9 filter even | map * 3 | for print
valid jetty
royal nymph
hoary sluice
valid jetty
#

char[] does exist and you can convert between them easily tho

hoary sluice
valid jetty
#

yeah

hoary sluice
#

this is noulith

1 to 10 filter even map (3*)
#

hm maybe the | isnt neccessary

hoary sluice
valid jetty
#

haskell forces you to put $ to understand exactly in what order you want things to happen but you could make it optional and guess the order if not specified

hoary sluice
valid jetty
#

imo instead of focusing on these semantics now you should focus on making functions be real lol

#

even x = % 2 x

hoary sluice
valid jetty
#

ok fair

hoary sluice
#

eg do i wanna make +-*/ functions

valid jetty
#

if you wanna go full functional style make +-*/ valid identifiers and define them in terms of their combinator equivalent

#

lol

#

with church numerals and everything

hoary sluice
valid jetty
#

true

#

i wanna make 0..10 ranges

#

i was thinking

hoary sluice
#
fn Point.+ = x + y
valid jetty
#

what if i make β€œ..” an arithmetic operator like + or -

hoary sluice
#

kotlin does pretty much that

valid jetty
#

then in the compiler you have the proper ast node with .. as the operator and the lhs/rhs properly parsed and i can just pipe them into Array::range

valid jetty
hoary sluice
#

any type that extends Comparable can be a range

valid jetty
#

what precedence does it have in kotlin

#

i’m assuming lowest but higher than ternaries

hoary sluice
#

idk

#

kotlin doesnt have ternary

valid jetty
#

so that 1+2..9 is 3..9

hoary sluice
#

that yes

valid jetty
hoary sluice
hoary sluice
#

ifs are always exprs

valid jetty
#

let x = y ? z : w in elle or in rust let x = if y { z } else { w } or in lua local x = if y then z else w end or in py x = z if y else w

valid jetty
hoary sluice
valid jetty
hoary sluice
#

idk thats what claude said it sounds wrong tho

valid jetty
#

try it lol

valid jetty
#

ok yep that seems about right

placid cape
#

ah you already sent it

hoary sluice
#

that seems wrong

#

no it doesnt

#

wait im stupid

#

that means -+ is evaluated before ..

valid jetty
#

ok well i need to leave in 25 mins so i’ll quickly get ready and if i have time i’ll make ranges in elle

valid jetty
#

@hoary sluice

#

loveee

if matches!(operator, TokenKind::Range | TokenKind::RangeEqual) {
    let node = AstNode::FunctionCall {
        name: "Array.range".into(),
        generics: vec![],
        parameters: vec![
            (location.clone(), *left),
            (location.clone(), *right),
            (
                location.clone(),
                AstNode::LiteralStatement {
                    kind: TokenKind::IntegerLiteral,
                    value: ValueKind::Number(
                        if operator == TokenKind::RangeEqual {
                            1
                        } else {
                            0
                        },
                    ),
                    location: location.clone(),
                },
            ),
        ],
        type_method: false,
        ignore_no_def: false,
        location: location.clone(),
    };

    let (ty, val) = self
        .generate_statement(func, module, node, ty.clone(), None, is_return)
        .expect(&location.error(
            "Unexpected error when trying to parse left side of an arithmetic operation"
        ));

    return Some((ty, val));
}
hoary sluice
#

i dont like that

#

imo .. and ..< is better

valid jetty
#

why

#

oh

#

hm

#

idk i copied rust

hoary sluice
#

maybe ..= and ..< so its clear

valid jetty
#

like this is literally rust code atp

valid jetty
#

rust wont give me the array it creates

#

but yeah

fleet cedar
#

Using .. for the kind of range that makes sense (right-exclusive) is better imo

valid jetty
#

yeah it is exclusive

valid jetty
#

2..=4 creates [2, 3, 4] (inclusive)

fleet cedar
#

That'd be inefficient

#

You can collect to a vec if you want that

hoary sluice
#

have fun

valid jetty
hoary sluice
valid jetty
#

wdym

valid jetty
#

they’ll be arrays until i make lazy iterators

hoary sluice
#

@valid jetty

dense sand
#

do yall ever sleep

valid jetty
#

i slept a solid 3 hours

nimble bone
#

@valid jetty you have aa gamer disease

valid jetty
#

should i make sugar where you can do

for i in 10 {
    io::dbg(i);
}
``` lol
royal nymph
#

this is better

valid jetty
#

already exists

valid jetty
#

i wrote it in like 5 mins because i had to leave lol

#

having Array::range already and a whole operator precedence system in the compiler made it pretty easy

hasty vessel
fleet cedar
#

Sounds like a scam

valid jetty
#

Tower x Game Download APK

#

wow that entire description is ai generated

#

lmfao

hoary sluice
#

delusional ai, as always

hasty vessel
hasty vessel
# hoary sluice delusional ai, as always

App Tower x Game APK refers to a platform that brings together a curated selection of games and applications tailored for Android devices. An APK (Android Package Kit) is a file format used to distribute and install apps on Android devices. This pairing ensures that users have access to premium-quality games with seamless installation processes.

#

top 10 most human paragraphs

hasty vessel
#

yes

hasty vessel
hoary sluice
#

i almost beat stereo madness first try

#

i think the cube jumps a little too far

#

the plane feels completely different

hasty vessel
#

PLANE?

#

i think you mean ship

hoary sluice
#

whatever

hasty vessel
placid cape
#

it's good to have syntax for simplifying certain things but on the other hand it's not very good if you have too many ways to do one thing

#

example - react

hoary sluice
placid cape
#

if you have too many ways to do the same thing then it's definitely not good

hoary sluice
#

id love for i in 10 tho

nimble bone
#

yop

placid cape
hoary sluice
dense sand
#

Onlocklearning is a nice channel

#

I first saw it on reels

twilit sigil
#

never understood them

placid cape
twilit sigil
fleet cedar
#

They're just linear functions, nothing fancy

hoary sluice
hasty vessel
fleet cedar
#

What aoc needs matrices

hoary sluice
#

Day 13 2024

hasty vessel
#

omg guys shiggy sent me an email

dense sand
#

i shall be terry davis

#

and now its centered :D

placid cape
#

@hoary sluice do you want to make bytecode for icps?

#

or just ast interpreter and then compiler

hoary sluice
#

no

#

yes

placid cape
#

I'm now trying qbe and surprisingly it's really easy

valid jetty
#

yes lol that’s why i chose it

#

no bullshit bloat

#

the only downside is less optimizations

hoary sluice
#

im probably gonna use llvm cause it might actually get xtensa support and its more supported in general, but rn im focusing on a working interpreter

valid jetty
#

but i can live with that

#

oh yeah and target support

#

true

#

qbe only supports arm, amd, and risc

hoary sluice
#

there is no way qbe will ever target xtensa

valid jetty
#

all for 64 bit only

placid cape
#

I want to try something easier and some day ill maybe try llvm

#

I did interpreted prog language only once and it was horrible heh

hoary sluice
#

Eigen compiler suite supports xtensa but thats not my main goal, just a big +

valid jetty
#

if you have any questions you can ask me i know a lot about it

hoary sluice
#

do i make IntegerLiteral and FloatLiteral, both 64 bit and worry abt smaller types later?

placid cape
#

well yeah

valid jetty
#

i have integer literal, char literal, long literal, and float literal

#

floats are strings in the token and are converted to a div

#

the others are i128

hoary sluice
#

what abt i8, u8, i16, u16

placid cape
valid jetty
#

255 is still an integer literal

hoary sluice
#

of

#

ok

valid jetty
#

its up to the compiler to interpret it to the size it should be but the lexer should have a "catch all" number for its literals which can hold the biggest type youre gonna have in the language

#

i chose i128 because it can hold u64 comfortably

hoary sluice
#

ill do i64 cause thats the max for aoc

valid jetty
#

yeah probably a good call i guess

hoary sluice
#

also i dont actually need floats since aoc never uses floats but thats taking it too far

valid jetty
#

lmfao

placid cape
#

imagine language without floats lol

valid jetty
#

i sort of regret implementing ranges

#

because now ur just always gonna type for i in 0..10 instead of for let i = 0; i < 10; i += 1

placid cape
#

the second one is currently more performant right?

valid jetty
#

yep

#

because the range creates an array

#

i guess that can be a reason

placid cape
#

Can't you change the syntax sugar to instead do the let i =......?

valid jetty
#

wdym

hoary sluice
twilit sigil
ionic lake
#

do we have a zen of elle like the zen of zig

#

or the zen of pythong

placid cape
# valid jetty wdym

instead of using array for range just make for i in 0..10 to be for let i = 0; i < 10; i += 1

hoary sluice
#

when elle borrow checker

ionic lake
#

when will elle save us from the ligma

valid jetty
#

i can probably just catch it here

hoary sluice
#

thats not maintainable

#

just make lazy iterators

valid jetty
#

lazy iterators implies traits and im not ready for that yet

hoary sluice
#

u can refactor it to traits later

valid jetty
#

i could just make an __next__ method i guess

hoary sluice
#

just make an iterator type that has a curval and a next method

valid jetty
#

there lazy range

use std/option;
use std/io;

struct Range {
    i32 current;
    i32 max;
    bool done;
};

fn Range::new(i32 low, i32 high, bool inclusive) {
    Range *range = malloc(#size(Range));
    *range = malloc(#size(Range));

    range.current = low;
    range.max = high + inclusive;
    range.done = false;

    return range;
}

fn Range::next(Range *self) -> Option<i32> {
    if !self.done {
        let res = Option::Some(self.current);
        self.current += 1;

        if self.current == self.max {
            self.done = true;
        }

        return res;
    }

    return Option::None();
}

fn main() {
    let range = Range::new(0, 10, true);

    while !range.done {
        io::dbg(range.next().unwrap());
    }

    io::dbg(range.next().unwrap());
}
hoary sluice
valid jetty
#

i could probably make it saner

hoary sluice
#

why that last unwrap

hoary sluice
valid jetty
valid jetty
valid jetty
#

i mean its not exactly rocket science

use std/option;
use std/io;

struct Range {
    i32 current;
    i32 max;
    i32 step;
    bool done;
};

fn Range::new(i32 low, i32 high, i32 step, bool inclusive) {
    Range *range = malloc(#size(Range));
    *range = malloc(#size(Range));

    range.current = low;
    range.max = high + inclusive;
    range.step = step;
    range.done = false;

    return range;
}

fn Range::next(Range *self) -> Option<i32> {
    if !self.done {
        let res = Option::Some(self.current);
        self.current += self.step;

        if self.current >= self.max {
            self.done = true;
        }

        return res;
    }

    return Option::None();
}

fn main() {
    let range = Range::new(0, 10, 2, true);

    while !range.done {
        io::dbg(range.next().unwrap());
    }
}
#

oh lol fuck

hoary sluice
#

what if the step is a function

hoary sluice
valid jetty
#

i did

valid jetty
#

oh idk

hoary sluice
#

0..9 step multiply(it, 2)

valid jetty
#

im preparing for the oop elle days

hoary sluice
#

nooo husk

valid jetty
#

(it will probably never have classes)

hoary sluice
#

yesssss πŸ˜ƒ

valid jetty
hoary sluice
valid jetty
#

you wouldnt have a case like that in a real langugage

hoary sluice
#

but u can implement it

valid jetty
#

what is it in this case

#

the current index?

hoary sluice
#

yes

#

well the value

#

fun ClosedRange.step()

placid cape
valid jetty
#

itll just get stuck at 0 * 2 = 0 and not step up by anything

#

silly

hoary sluice
valid jetty
#

wait does that thing mean self.current += multiply(self.current, 2) or self.current = multiply(self.current, 2)

#

because with += you get this

#
use std/option;
use std/io;

struct Range {
    i32 current;
    i32 max;
    void *step_fn;
    bool done;
};

fn Range::new(i32 low, i32 high, fn *step_fn, bool inclusive) {
    Range *range = malloc(#size(Range));
    *range = malloc(#size(Range));

    range.current = low;
    range.max = high + inclusive;
    range.step_fn = step_fn;
    range.done = false;

    return range;
}

fn Range::next(Range *self) -> Option<i32> {
    if !self.done {
        let res = Option::Some(self.current);
        fn *step_fn = self.step_fn;
        self.current = (i32)step_fn(self.current);

        if self.current >= self.max {
            self.done = true;
        }

        return res;
    }

    return Option::None();
}

fn main() {
    let range = Range::new(2, 10000, fn(i32 i) -> i * 2, true);

    while !range.done {
        io::dbg(range.next().unwrap());
    }
}
``` ignore the fn syntax thats another unfinished part of the language
hoary sluice
valid jetty
hoary sluice
valid jetty
#

(4374 += (4374 * 2)) >= 10000 so it stops

#

oh

hoary sluice
#

oh its 10k ok

valid jetty
#

if i make it = you get this

placid cape
valid jetty
#

the silly

hoary sluice
#

u have anonymous functions

#

??

valid jetty
#

yes??

hoary sluice
#

since when

valid jetty
#

but non-capturing

#

since months ago

#

scope capturing is a really hard thing to implement

#

so i havent yet

#

theyre called lambdas internally if you wanna grep the src code

hoary sluice
valid jetty
#

nono u dont understand lol

#

when you create a lambda you have to create an environment struct with all variables from surrounding scopes that are used in the lambda

#

then move them both at once

hoary sluice
#

what do u do for ifs

valid jetty
#

and call the lambda with the env and resolve env variables

#

scopes for ifs and stuff are just enforced in the compiler

#

in IR there are no scopes

fleet cedar
#

The difference is that the closure scope might exist after the scope has exited

valid jetty
#

variables live in every scope

hoary sluice
#

i dont think this is idiomatic

valid jetty
#

i have an example for how in theory capturing lambdas could exist

use std/io;

struct Env { i32 a; };
struct Function { Env env; void *func; };

fn add(i32 a) {
    Env env = Env { a = a };
    fn *func = fn(Env env, i32 b) -> env.a + b;

    return Function {
        func = func,
        env = env
    };
}

fn main() {
    let res = add(13);
    fn *curried = res.func;
    io::dbg((i32)curried(res.env, 26));
}
valid jetty
hoary sluice
#

its still extremely slow

valid jetty
#

in elle scopes are just a made-up concept

hoary sluice
#

im cloning the env 3 times

valid jetty
#

a hashmap from a variable name to its type and internal IR value

#

and every new block pushes a scope

#

when the scope ends its popped

valid jetty
hoary sluice
valid jetty
#

why

hoary sluice
#

that was my first time using rust / refcells

valid jetty
#

why do you clone previous

hoary sluice
#

/ rc

#

idk

#

thats old code

valid jetty
#

weird

#

but sure

hoary sluice
#

hey i used Integer.parseInt in kotlin

valid jetty
#

should i finally rewrite this in idiomatic elle lol

use std/string;
use std/cast;
use std/io;

fn main() {
    i32 highestScore = 0;
    string winner = (string)malloc(BUF_SIZE * #size(char));
    defer free(winner);

    while true {
        string person = io::input("Enter a person's name (or 'stop'): ");
        defer free(person);

        if person == "stop" {
            break;
        }

        i32 score = i32::parse(io::input(string::format("Enter {}'s score: ", person)));

        if score > highestScore {
            highestScore = score;
            strcpy(winner, person);
        }
    }

    io::printf("The winner is {} with a score of {}", winner, highestScore);
}
hoary sluice
#

no

#

relic

valid jetty
#

vampire dentist reli

#

c

placid cape
#

#size() is something like built-in function?

#

compile time*

valid jetty
#

its called a "directive"

#

yes compile time

#

there are 3 atm, #size (gives you the size of the type of whatever expr you put inside) #len (gives you the length of a static array) #i (to be called inside a foreach to get the index for the current value)

#

#i doesnt really make sense unless you see it used

frosty obsidian
#

insane

dense sand
#

right

valid jetty
#

there is also a distinction between directives (with #) and attributes (with @ )

#

attributes are used more like this

#

or this

#

or this

valid jetty
#

you can alias external C functions to put them into a namespace or give them a different name

placid cape
#

The attribute thing is cool

valid jetty
#
external fn isalnum(char arg) @alias("char::is_alphanumeric") -> bool;
``` this allows you to do `'a'.is_alphanumeric()` because of how the sugaring works
#

:3

#

the alias thing also lets you do this

#

where you want to have the same function but under 2 names

placid cape
#

explode

#

php flashback

placid cape
#

I thought its function from libc

valid jetty
#

it is.. sorta

#

its not exactly from libc it just means a function where we dont know the body

#

x::y is sugar for x.y which is a valid identifier for symbols in object files

placid cape
#

can you show IR?

valid jetty
#
type :ElleMeta = { l, l, w, l, l, w, w }
data $.11 = { b "wa", b 0 }
data $.14 = { b "ra", b 0 }
export function l $string.repeat(l %self.687, w %count.688) {
@start
    # ... omitted for brevity
}
function l $example.foo(l %x.8) {
@start
    %tmp.9 =l call $string.repeat(l %x.8, w 5)
    ret %tmp.9
}
export function w $main() {
@start
    %tmp.12 =l call $example.foo(l $.11)
    %tmp.13 =w call $puts(l %tmp.12)
    %tmp.15 =l call $example.foo(l $.14)
    %tmp.16 =w call $puts(l %tmp.15)
    ret 0
}
#

this is basically what it generates

#

with some bloat omitted

#

the aliasing is entirely done in the compiler

#

wait

#

i never called example::bar

#

ok yeah as i expected doesnt change anything

#

still calls $example.foo

valid jetty
#

you already could from a long time ago

#

but now you can namespace them to organise them better

#

aliasing is optional

valid jetty
placid cape
valid jetty
#

yes

#

functions have an aliased field which is just Option<String>

#

or alternatively for a more useful usecase

#

to make printf in C consistent with the other printing functions (io::println, io::dbg, io::printf, etc)

#

when you call io::cprintf it "replaces" it to just printf which is what the symbol is actually called in the object file

placid cape
#

nice

valid jetty
#

it saves you from having to write wrappers such as

external fn puts(string arg) -> i32;

fn io::cputs(string arg) {
    return puts(arg);
}
``` when it can just be
```rs
external fn puts(string arg) @alias("io::cputs") -> i32;
placid cape
#

im gonna implement native functions

#

πŸ‘

#

i also have transpiler for lua and js xd

#

also python but bit broken for blocks

valid jetty
#

i should totally make a js transpiler

#

it would be almost a 1-1 translation except for pointers

placid cape
#

thats pretty easy

valid jetty
#

how tf does the concept of ```rs
let x = 0;
let y = &x;

placid cape
valid jetty
#

thats wrong though because x and y have different types

#

the js assumes they have the same type

#

but whatever

#

i see where its coming from

hoary sluice
valid jetty
#

no but even then thats wrong actually

hoary sluice
#

A dynamically typed and quite verbose language created (inexplicably) mainly to solve Advent of Code problems.

valid jetty
#

this is what it should look like

function main() {
    let y_addr = {};
    let x_addr = {};
    x_addr.value = 0;
    let x = x_addr.value;
    y_addr.value = x_addr;
    let y = y_addr.value;
    y.value = 1;
    x = x_addr.value;
    console.log(x);
}
#

looks like slop

#

because it is

#

lemme write this in elle to see how it compares

#
export function w $main() {
@start
    %y.addr.9 =l alloc8 8
    %x.addr.7 =l alloc8 4
    storew 0, %x.addr.7
    %x.6 =w loadw %x.addr.7
    storel %x.addr.7, %y.addr.9
    %y.8 =l loadl %y.addr.9
    storew 1, %y.8
    %x.6 =w loadw %x.addr.7
    %tmp.13 =w call $printf(l $.12, ..., w %x.6)
    ret 0
}
``` holy shit LMAO
#

other than the stack reserving being at the top this is like exactly the same i made them match

hoary sluice
#

he doesnt have 2d arrays or nested math, crazy that he solved aoc with it

valid jetty
# hoary sluice wtf is this

allocate memory for the address of x and y
set x to 0
x = the current value at x_addr
set y to the addr of x
set the value at y to 1
youre about to print x so get its current value then print it

#

its what this program would transpile to

fn main() {
    let x = 0;
    let y = &x;
    *y = 1;
    printf("%d", x);
}
valid jetty
#

(what it actually generates btw)

hoary sluice
#

oh is this another bad js feature

valid jetty
#

no what

#

just the fact that this

function main() {
    let x = {};
    let y = x;

    y.a = 1;
    console.log(x.a); // 1
}

main()
#

objects and arrays are references

hoary sluice
#

im so confused right now

valid jetty
#

when you set y to x ur setting it to the reference of the object not the object itself

#

so when you mutate y youre also mutating x

#

that can be a bad feature depending on who you ask

hoary sluice
#

yes

#

but why is that a thing in js

valid jetty
#

idk

placid cape
#

because js

valid jetty
#

yeah

placid cape
#

js is the most cursed lang

valid jetty
placid cape
#

when it comes to internals

valid jetty
#

the IR is right under it

placid cape
#

i see

valid jetty
#

i need to get to writing my aoc solutions in elle so i can brag on the subreddit

#

maybe ill do that tonight

#

sometimes i hate list comprehension because wtf does this mean looking at it 2 weeks later

placid cape
#

youtube music just played me rickroll lmao

hoary sluice
ornate quiver
hoary sluice
#

bro tsoding is not real

#

fucking c3???

#

emacs????????

valid jetty
valid jetty
#

made by a single dev

#

basically

viscid grove
ornate quiver
#

no clue

viscid grove
#

what even is that div

ornate quiver
#

channels list

viscid grove
#

it has no children though

#

is it something for tabbing?

valid jetty
#

@hoary sluice and this is why i wanted to make tuple syntax

#

it could look like this

#

i think im just gonna suck it up and do that

#

im basically making a whole parser in the get_type fn atp

placid cape
#

this compiles successfully

#

time to sleep, gn

valid jetty
#

yay

valid jetty
#

i didnt wanna bother to make tuple parsing so tuples are an alias

#

as in this

#

you do $(x, y) instead of (x, y)

#

because easier to parse to make it just a function

#

although parsing it properly wouldnt be too bad
-> enter "wrapped statement" parsing
-> reach the end
-> its a comma
-> rewind to the start of the wrapped statement parsing
-> enter "tuple" parsing instead
-> yield tokens until comma
-> yield tokens until )
-> lhs is first arg to Tuple::new
-> rhs is secon arg

boom

#

if you need more than 2 fields in your tuple use a struct for god's sake

#

let x: (i32, i32, i32, i32, i32);

valid jetty
#

ok yeah

#

works after defining

fn Tuple::__equals__<T, U>(Tuple<T, U> self, Tuple<T, U> other) {
    return self.x == other.x && self.y == other.y;
}

fn Tuple::__hash__<T, U>(Tuple<T, U> self, i32 capacity) {
    i64 hash_x = self.x.__hash__(capacity);
    i64 hash_y = self.y.__hash__(capacity);
    i64 combined = hash_x * 31 + hash_y;
    return __internal_hash_mod(combined, capacity);
}
placid cape
#

Can't you just make function with $ as name using @alias ?

placid cape
hoary sluice
#

@valid jetty do u love

if float {
    self.next().ok_or(Error::NotANumber)?.is_ascii_digit().then_some(()).ok_or(Error::NotANumber)?;
}
#

this is prob better

if float {
    self.next().ok_or(Error::UnexpectedEndOfFile)?.is_ascii_digit().then_some(()).ok_or(Error::NotANumber)?;
}
#

nvm its not even needed

#

maybe it is, do i keep this valid?

#

that would cause problems for 123.function

placid cape
#

it works

hoary sluice
#

to get 123.0

placid cape
#

huh?

#

you mean flots?

hoary sluice
#

f32 x = 123.;

#

is this valid

placid cape
#

no

hoary sluice
#

ok

placid cape
#

wait no

#

it is valid

#

sorry

hoary sluice
#

can u do 123.function

placid cape
#

not implemented

#

i only have simple functions, variables, loops

#

and conditions

dense sand
#

add inline C like bun has trolley

hoary sluice
#

hm

dense sand
#

(altought its basically now possible with extern)

dense sand
#

How tf am i supposed to resolve merge conflict in lock file

#

like i just wanna keep the current one

fleet cedar
#

Then do that

ionic lake
#

typically you don't have to

#

just run $pm install again and it should fix them

placid cape
#

yeeeyyy

dense sand
#

when i try to merge the branches in console it says that all is up to date

hoary sluice
valid jetty
valid jetty
#

but yeah silly

fn Tuple::new<T, U>(T x, U y) {
    Tuple<T, U> *tuple = malloc(#size(Tuple<T, U>));
    *tuple = malloc(#size(Tuple<T, U>));

    tuple.x = x;
    tuple.y = y;

    return tuple;
}

external fn Tuple::new<T, U>(T x, U y) @alias("$") -> (T, U);
#

ughhh i cant do day 15 properly because something is wrong with my HashSet implementation when you delete something

hoary sluice
valid jetty
#
  1. is a syntax error
#

wait do hashsets usually have NEVER_USED for slots and then EMPTY or TOMBSTONE for slots that had a value at one point but were removed

#

currently i just use EMPTY for all slots that currently have no value whether they had a value before or not

#

and it breaks the linear probing if you remove things from the set

#

right here

#

something in the linear probing is broken

#

it doesnt find the cell to remove because things have been removed previously

#

but still adds afterwards

#

because the function is this

fn push((i32, i32) b, (i32, i32) dir, HashSet<(i32, i32)> *bs, HashSet<(i32, i32)> *ws) {
    let npos = $(b.x + dir.x, b.y + dir.y);

    if ws.contains(npos) {
        return false;
    }

    if bs.contains(npos) {
        if !push(npos, dir, bs, ws) {
            return false;
        }
    }

    bs.remove(b);
    bs.add(npos);
    io::println(bs);
    return true;
}
placid cape
valid jetty
#

opinions on i32[#] -> HashSet<i32> * just like i32[] -> Array<i32> *

fleet cedar
#

Sets aren't as fundamental as lists

valid jetty
#

yeah that’s why i’m torn on it

valid jetty
# placid cape yeeeyyy

if you change it to f32 do you get 0.000000 when printing even though the float isn’t 0?

dense sand
#

i want to merge app/auth into main

valid jetty
#

IT WORKS

#

i changed it to have NEVER_USED for cells that have never had any value but TOMBSTONE for cells that have had a value but it was removed

#

then i just change this to be silly

fn HashSet::remove<T>(HashSet<T> *self, T value) -> bool {
    i32 idx = value.__hash__(self.capacity);
    i32 start_idx = idx;

    while true {
        if (void *)self.table[idx] == NEVER_USED {
            return false;
        }

        if ((void *)self.table[idx] != TOMBSTONE) && self.table[idx] == value {
            self.table[idx] = (T)TOMBSTONE;
            self.size -= 1;
            return true;
        }

        idx = (idx + 1) % self.capacity;

        if idx == start_idx {
            return false;
        }
    }
}
#

and i get the same answer as the py so slay

#

this no longer breaks the linear probing chain because cells that had a value but dont anymore now have TOMBSTONE so the linear probing will just skip over them

valid jetty
#

C secretly promotes floats to doubles when theyre printed

#

your code is keeping it as a float so the first 32 bits are empty

#

so you get 0

placid cape
#

oh lol

#

didnt know that

valid jetty
#

c is really weird

#

well technically its not the first 32 bits

#

because floats use IEEE-754

#

but the same concept applies

hoary sluice
hoary sluice
placid cape
#

okay now time to implement scopes heh

#

but first i should probably fix this to throw compilation error blobcatcozy

valid jetty
placid cape
valid jetty
#

ooo looks nice

placid cape
#

ill make better messages later

#

with hints

#

nice looks like type checking works

#

large structure lol

#

ignore qbe output files xdd

#

assembly blobcatcozy

valid jetty
#

insane

placid cape
#

i'll use interpreter probably only for repl

#

but need to make sure it's consistent with compiled version

valid jetty
#

is it open source?

placid cape
#

then i'll make it open source

#

i don't have a lot of closed source projects

#

im making open source everything if it's not paid job :D

valid jetty
#

lol yep thats how i work too

#

btw @hoary sluice do you plan to leech off of rust for generics and data structures?

valid jetty
#

if yes thats good lol

#

implementing from scratch is so painful

placid cape
valid jetty
#

true lol

#

the fact that this is valid syntax now omg

#
for pos in [npos, lpos, rpos] {
    if bs.contains(pos) {
        if !push2(pos, dir, bs, ws) {
            return false;
        }
    }
}
#
Array<void *> *poss = Array::new(npos, lpos, rpos);

for i32 i = 0; i < poss.len(); i += 1 {
    Tuple<i32, i32> *pos = poss[i];

    if bs.contains(pos) {
        if !push2(pos, dir, bs, ws) {
            return false;
        }
    }
}
dense sand
#

wow i hate paging

#

i hate dsa

#

even in fucking osdev

#

they are everywhere

placid cape
#

if donee

valid jetty
#

woooo day 15 done in elle

#

wait

#

p2 is wrong

#

fuck

#

what

#

its right for the sample

#

😭

dense sand
#

thats just how it is

valid jetty
#

it turns out

#

the python one is wrong

#

somehow??

#

the elle one is right

#

the answer is 1576353

#

how did this happen

#

ok i fixed it

placid cape
#

niceee

#

I need to solve 2015 day 8

#

want to solve at least one puzzle every day

valid jetty
#

before i solved the puzzles by encoding 2 numbers into a single number with bit operations so that i can hash them in sets but now you can hash tuples so i need to go back and fix my solutions lol

#

idk why

#

but this takes almost a minute in elle and a few ms in py

#

weird

#

nvm i see why i think?

placid cape
hoary sluice
#

its parser time

hoary sluice
#

@valid jetty please make this valid elle

DECLARE FUNCTION ADDITION (ITERABLE VARIADIC ARGUMENTS A OF TYPE INTEGER 64): RETURNS INTEGER 64;
DEFINE FUNCTION ADDITION (ITERABLE VARIADIC ARGUMENTS A OF TYPE INTEGER 64): RETURNS INTEGER 64
        {
                DECLARE MUTABLE VARIABLE SUM OF TYPE INTEGER 64;
                DEFINE MUTABLE VARIABLE SUM OF TYPE INTEGER 64 EQUAL TO CONSTANT ZERO;
                DECLARE ITERATION IT OVER ITERABLE A OF TYPE ITERABLE VARIADIC ARGUMENTS OF TYPE INTEGER 64;
                DEFINE ITERATION IT OVER ITERABLE A OF TYPE ITERABLE VARIADIC ARGUMENTS OF TYPE INTEGER 64
                        {
                                DECLARE IMMUTABLE VARIABLE CURRENT OF TYPE INTEGER 64;
                                USE IMMUTABLE VARIABLE CURRENT OF TYPE INTEGER 64 AS ITERATION VALUE;
                                INCREMENT SUM BY VARIABLE CURRENT;
                        }
                RETURN VARIABLE SUM;
        }
placid cape
#

so this is the thing you were typing for like 7 minutes husk

hoary sluice
#

yes

placid cape
#

sql vibe

hoary sluice
#

i was gonna say smth about the word variadic and then got distracted

hoary sluice
placid cape
#

xddddd

#

is there a language that has syntax like this?

hoary sluice
#

cobol is pretty close

hoary sluice
valid jetty
#

im so confused

#

wtf is it doing for x.values()

#

why are they numbers and not sets

#

am i insane

fn HashMap::keys<T, U>(HashMap<T, U> *self) -> T[] {
    let array = Array::with_capacity(self.size);

    for i32 i = 0; i < self.capacity; i += 1 {
        if self.table[i].full && (void *)self.table[i].key != EMPTY {
            array.push(self.table[i].key);
        }
    }

    return array;
}

fn HashMap::values<T, U>(HashMap<T, U> *self) -> U[] {
    let array = Array::with_capacity(self.size);

    for i32 i = 0; i < self.capacity; i += 1 {
        if self.table[i].full && (void *)self.table[i].value != EMPTY {
            array.push(self.table[i].value);
        }
    }

    return array;
}
fleet cedar
#

Misinterpreted pointers?

valid jetty
#

yeah i think so

hoary sluice
#

is that the address of the sets

valid jetty
#

i think yes but truncated to i32

fleet cedar
#

Good stuff

valid jetty
#

yeah lol

#

looks about right

#

how

#

how does that happen

#

U is not i32

placid cape
placid cape
#

Just want to clean-up things first

velvet fog
#

gaming

valid jetty
#

maybe py just has very optimized data structures

#

do i do some horrid thing in the elle version

fn dfs(string[] grid, HashSet<(i32, i32)> *v, (i32, i32) rc, i32 p) {
    let a = HashSet::new<(i32, i32)>();
    let stack = [rc];

    while !stack.is_empty() {
        let item = stack.pop();
        let x = item.x;
        let y = item.y;

        if v.contains(item) || x < 0 || x >= grid.len()
            || y < 0 || y >= grid[0].len() || grid[x][y] != p {
            continue;
        }

        v.add(item);
        a.add(item);

        for d in #[$(x + 1, y), $(x - 1, y), $(x, y + 1), $(x, y - 1)] {
            if !v.contains(d) {
                stack.push(d);
            }
        }
    }

    return a;
}
#
def dfs(r, c, p):
    a = set()
    stack = [(r, c)]

    while stack:
        x, y = stack.pop()

        if (x, y) in v or x < 0 or x >= len(grid) or y < 0 or y >= len(grid[0]) or grid[x][y] != p:
            continue

        v.add((x, y))
        a.add((x, y))

        for nx, ny in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
            if (nx, ny) not in v:
                stack.append((nx, ny))
    return a
#

istg if its the fact that string.len() is O(n)

#

let me convert the grid to a char[][]

#

nope

#

same speed

#

maybe its because tuples with $() are heap allocated

hoary sluice
#

Why are u doing dfs in day 12

valid jetty
#

this is a precomputation to find all the areas

#
[solution.le:120:13] HashMap<i32, Array<HashSet<Tuple<i32, i32>*>*>*>* rs = <{
    65 => [{(0, 0), (0, 1), (0, 2), (0, 3)}]
    66 => [{(1, 1), (2, 1), (2, 0), (1, 0)}]
    67 => [{(2, 2), (1, 2), (2, 3), (3, 3)}]
    68 => [{(1, 3)}]
    69 => [{(3, 0), (3, 1), (3, 2)}]
} at 0x600000378090>
#

that type is a little cursed but ignore that

#

thats for this

AAAA
BBCD
BBCC
EEEC
#

the key is the ascii value of the plot name

#

it works its just awfully slow

valid jetty
#

lmfaooo

hoary sluice
#

time every part of it

hoary sluice
#

are your stringr mutable

#

if not just store their length too

#

if yes just store their length too as well

#

i saw 5:59 on the clock and thought i was about to miss aoc

valid jetty
#

strings are just char*

hoary sluice
#

do i do it

valid jetty
#

i figured out a big performance loss i think?

valid jetty
#

visited set is killing performance i think bool[][] would work better than HashSet<(i32, i32)>

#

yeah holy shit

#

that just completely fixed performance

#

wtf

#

why was that so awfully slow

#

not as fast as py but imo this is reasonable

#

it took 1 min 13s to compute before

#

with HashSet<(i32, i32)> *

hoary sluice
valid jetty
#

what were you expecting

hoary sluice
#

idk

hoary sluice
placid cape
#

Not pypy

valid jetty
#

im sure py has a very optimized set impl mine is just sort of naive

hoary sluice
valid jetty
#

no lol its always O(1)

hoary sluice
#

wait ur right

#

but ur using sets in python right

#

ig they optimize this

valid jetty
#

v[x][y] is

(assuming v is a ptr)

let intermediate = load(v + (x * size))
let res = load(intermediate + (y * size))

valid jetty
#

theres a lot of optimization you can make

#

mine is just kinda a thingie

fn HashSet::contains<T>(HashSet<T> *self, T value) -> bool {
    i32 idx = value.__hash__(self.capacity);
    i32 start_idx = idx;

    while true {
        if (void *)self.table[idx] == NEVER_USED {
            return false;
        }

        if ((void *)self.table[idx] != TOMBSTONE) && self.table[idx] == value {
            return true;
        }

        idx = (idx + 1) % self.capacity;

        if idx == start_idx {
            return false;
        }
    }
}
``` im sure it could be made much faster
#

its not the most naive because i still use linear probing but yeah

#

i might need to implement this

#

yeah this

placid cape
#

πŸ‘

hoary sluice
#

@valid jetty @placid cape do yall use visitors

valid jetty
valid jetty
#

i have used them before

#
namespace Internal
{
    InfluxDBClient client(INFLUXDB_HOST, INFLUXDB_ORGANISATION, INFLUXDB_BUCKET, INFLUXDB_TOKEN);
    Point sensor("Readings");
    DHT dht(DHT_PIN, DHT_TYPE);
    Adafruit_SGP30 sgp;

    struct Visitor 
    {
        std::string _measurement;
        Visitor(std::string measurement) : _measurement(measurement) {};

        void operator() (float value)const 
        {
            sensor.addField(_measurement.c_str(), value);
        }

        void operator() (uint16_t value)const 
        {
            sensor.addField(_measurement.c_str(), value);
        }
    };
}
hoary sluice
#

A visitor pattern is a software design pattern that separates the algorithm from the object structure. Because of this separation, new operations can be added to existing object structures without modifying the structures. It is one way to follow the open/closed principle in object-oriented programming and software engineering.
In essence, the ...

valid jetty
#
for (const auto& pair : measurements) 
{
  auto measurement = pair.first;
  auto value = pair.second;
  apply_visitor(Visitor(measurement), value);
}
#

but i dont usually have a need for them

hoary sluice
#

thats not the visitor im talking abt

valid jetty
#

oh

#

is this not just overloading

placid cape
#

im just going through ast

valid jetty
#

i do it recursively

placid cape
#

Yea same

hoary sluice
#

you implement Visitor for the AstNode class and then use that for all astnodes

#

i just have a recursive match

valid jetty
#

yeah thats what i do lol

placid cape
#

same

valid jetty
#

recursive for stmts otherwise goes to parse an expr which parses with regards to arithmetic and operator precedence