Live data from Hacker News

Show HN: Cicada – A scripting language that integrates with C

github.com

31–40 of 41 posts

Re: Show HN: Cicada – A scripting language that integrates with C

#31
post #23

> Uses aliases not pointers, so it's memory-safe How does it deal with use after free? How does it deal with data races? Memory safety can't be solved by just eliminating pointer arithmetic, there's more stuff needed to achieve it

There’s no multithreading so race conditions don’t apply. That simplifies things quite a bit. There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, an…

I mean, that's a neat tradeoff, however..

> There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, and in no case is there any dangling ‘pointer’ (member or alias) pointing to unallocated memory. Does this answer your question?

Does this mean that Cicada will happily and wildly leak memory if I allocate short lived objects in a loop?

Why don't you just add some reference counting or tracing GC like everybody else

> 1) members can be removed;

Does this causes use after free if somebody had access to this member? Or it will give an error during access?

Re: Show HN: Cicada – A scripting language that integrates with C

#32
post #18

The for loop is odd. Why is the word counter in there twice? counter :: int for counter in ( print(counter) print(" ") ) Using backfor to count backwards is an odd choice. Why not overload for? backfor counter in print(counter, " ") This is confusing to me. Maybe I'm misunderstanding the design principles, but the syntax seems unintuitive.

Yeah this is why the syntax is customizable.. maybe it’s not optimal. The example I gave was strange and I’ll have to change it. Not sure what I was trying to show there. The basic syntax is just: for counter in print(counter) backfor counter in print(counter) It’s not overloaded because ‘for’ is basically a macro, expanding to ‘iterate, increment counter, break on counter > 5’ where ‘>’ is hard-coded. If ‘for’ was a…

Just do for counter in .rev(), which would iterate in a reversed range.

IMO it's poinless to distinguish synctactically between iterating forwards and backwards, specially if you also support things like for counter in .map({ return args[1] * 2) to irate on even numbers (the double of each number), rather than having to define a fordoubled macro. I mean, adding method like map and rev to ranges is more orthogonal and composes better. (See for example iterators in Rust)

Not that I don't like syntactic flexibility. I am a big fan of Ruby's unless, for example

Re: Show HN: Cicada – A scripting language that integrates with C

#33
post #23

Earlier quoted context omitted.

There’s no multithreading so race conditions don’t apply. That simplifies things quite a bit. There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, an…

I mean, that's a neat tradeoff, however.. > There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, and in no case is there any dangling ‘pointer’ (memb…

No, there are both referenced-based and tracing-based GC routines that will deallocate short-lived objects. Sorry, I was just trying to enumerate the ways memory goes out of scope to show that none of those ways results in an invalid pointer _within the scripting language_.

The safety comes because there is no way to access a pointer address within the scripting language. The main functionality of pointers is replaced by aliases (e.g. a = @b.c, a = @array[2], etc.). The only use of pointers is behind the scenes, e.g. when you write ‘b.c’ there is of course pointer arithmetic behind the scenes to find the data in member ‘b’.

Having said that, it is certainly possible for a C callback routine to store an internal pointer, then on a second callback try to use that pointer after it has fallen out of scope. This is the only use-after-free I can imagine.

Re: Show HN: Cicada – A scripting language that integrates with C

#34
post #23

Earlier quoted context omitted.

There’s no multithreading so race conditions don’t apply. That simplifies things quite a bit. There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, an…

I mean, that's a neat tradeoff, however.. > There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, and in no case is there any dangling ‘pointer’ (memb…

Also, if someone else has access to the member, meaning that there is an alias to the member, then the reference count should reflect that. Here’s an example:

i :: int | 1 reference

a := @i | 2 references

remove i | 1 reference

The data originally allocated for ‘i’ should persist because its reference count hasn’t hit zero yet.

Re: Show HN: Cicada – A scripting language that integrates with C

#35
post #18

Earlier quoted context omitted.

Yeah this is why the syntax is customizable.. maybe it’s not optimal. The example I gave was strange and I’ll have to change it. Not sure what I was trying to show there. The basic syntax is just: for counter in print(counter) backfor counter in print(counter) It’s not overloaded because ‘for’ is basically a macro, expanding to ‘iterate, increment counter, break on counter > 5’ where ‘>’ is hard-coded. If ‘for’ was a…

Just do for counter in .rev(), which would iterate in a reversed range. IMO it's poinless to distinguish synctactically between iterating forwards and backwards, specially if you also support things like for counter in .map({ return args[1] * 2) to irate on even numbers (the double of each number), rather than having to define a fordoubled macro. I mean, adding method like map and rev to ranges is more orthogonal and…

“IMO it's pointless to distinguish syntactically between iterating forwards and backwards” — I completely agree. It’s really a compiler-macro limitation that’s preventing me from doing this.. though I don’t have to go that route.

I think what you’re suggesting would require the syntax to produce a proper iterator type, which it doesn’t currently do. That’s definitely worth considering — then you could attach methods, etc.

Thanks for the suggestion! I’ll think about the best way to fix this..

Re: Show HN: Cicada – A scripting language that integrates with C

#36
post #20
post #17

Earlier quoted context omitted.

[flagged]

Yes there are lots of runtime checks.. unfortunately, but I always fork the time-consuming calculations into C anyway so those checks don’t really affect overall performance much. Scripted functions have no set arity, and the same applies to callback C functions. Scripted functions collect their arguments inside an ‘args’ variable. Likewise, each C function has a single ‘argsType’ argument which collects the argument…

[flagged]

Re: Show HN: Cicada – A scripting language that integrates with C

#37
post #36
post #20

Earlier quoted context omitted.

Yes there are lots of runtime checks.. unfortunately, but I always fork the time-consuming calculations into C anyway so those checks don’t really affect overall performance much. Scripted functions have no set arity, and the same applies to callback C functions. Scripted functions collect their arguments inside an ‘args’ variable. Likewise, each C function has a single ‘argsType’ argument which collects the argument…

[flagged]

Yes and the simplicity extends to function definitions too, since you don’t have to specify any type info. E.g.

f :: { ; print(args) }

Brevity is especially nice for inline/anonymous functions.

You can definitely use args.num, args.type[], and args.indices[] to figure out which optional parameters were passed, but I’ve decided that it’s usually easier to pass a full set of parameters into C and have the scripted wrapper handle the optional params. This is easy in Cicada because of ‘code substitution’ (one of the innovations I’m proudest of and if you’ve seen this elsewhere please let me know!). Example:

callC :: {

    mandatoryArgs :: { int, int }

    optionalArgs :: { str :: string; str = “default” }

    code

    mandatoryArgs = args

    optionalArgs(), (optionalArgs
}

Then you can call it with or without modifying the optional parameters from their default values.

callC(2, 3) | uses the default string

callC(2, 3; str = “modified param”)

callC() runs its arguments as a function, substituted into the params variable, allowing the arguments to modify params. This is weird and I haven’t seen it elsewhere, but it’s very useful.

Re: Show HN: Cicada – A scripting language that integrates with C

#38
post #34

Earlier quoted context omitted.

I mean, that's a neat tradeoff, however.. > There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, and in no case is there any dangling ‘pointer’ (memb…

Also, if someone else has access to the member, meaning that there is an alias to the member, then the reference count should reflect that. Here’s an example: i :: int | 1 reference a := @i | 2 references remove i | 1 reference The data originally allocated for ‘i’ should persist because its reference count hasn’t hit zero yet.

[deleted]

Re: Show HN: Cicada – A scripting language that integrates with C

#39
post #33

Earlier quoted context omitted.

I mean, that's a neat tradeoff, however.. > There’s actually no ‘free’, but in the (member -> variable data) ontology of Cicada there are indeed a few ways memory can become disused: 1) members can be removed; 2) members can be re-aliased; 3) arrays or lists can be resized. In those conditions the automated/manual collection routines will remove the disused memory, and in no case is there any dangling ‘pointer’ (memb…

No, there are both referenced-based and tracing-based GC routines that will deallocate short-lived objects. Sorry, I was just trying to enumerate the ways memory goes out of scope to show that none of those ways results in an invalid pointer _within the scripting language_. The safety comes because there is no way to access a pointer address within the scripting language. The main functionality of pointers is replace…

Okay, this is the usual way to perform safe memory management in managed / high level programming languages.. it was just that your "alias" terminology threw me off

Note that you can add multithreading later if you adopt message passing / actor model. Even Javascript, which is famously single threaded, gained workers with message passing at some point

Re: Show HN: Cicada – A scripting language that integrates with C

#40
post #33

Earlier quoted context omitted.

No, there are both referenced-based and tracing-based GC routines that will deallocate short-lived objects. Sorry, I was just trying to enumerate the ways memory goes out of scope to show that none of those ways results in an invalid pointer _within the scripting language_. The safety comes because there is no way to access a pointer address within the scripting language. The main functionality of pointers is replace…

Okay, this is the usual way to perform safe memory management in managed / high level programming languages.. it was just that your "alias" terminology threw me off Note that you can add multithreading later if you adopt message passing / actor model. Even Javascript, which is famously single threaded, gained workers with message passing at some point

Yes, multithreading seems to be a consistent theme among the comments.. so I should definitely look into that. Thanks for the comment. (I actually haven’t done much threaded programming myself so this would be a learning experience for me..)
Post reply on HN