The Opaque type is used for extern types like for interoping with C or environment provided APIs.
->
raw pointer
@ptr
raw pointer alias
@fptr
fat pointer
@vptr
vtable pointer
@ref
reference
@extern
extern type uses @opaque
underneath because the size is not known, nor is it dynamic.
Silicon has no this
keyword. Silicon has no real methods or dispatch. It has TDFD or whatever.
Silicon is structurally typed by default like Go
. Silicon is a flexible language with modes and defaults.
Interfaces in Silicon are just like traits like Rust
, they're nominally typed and can be applied to types after the fact.
this
/ self
is just the first parameter.
@type iText:trait 'T = {
@fn toUpperCase:string value:T
}
# takes a string pointer and returns void
## ->str => void
@fn toUpperCase:void self:->str
self.map(
@fn _ index,val
@if val in 65..90
@then << 4
@else val
@
)
@
// TODO: likely just add an @alias
keyword
Silicon has modes. It can by dynamically typed, statically typed, interpreted and compiled. It can be memory managed with various GC implementations, it can be manuall memory managed or managed with locality
like OCaml or borrower checker
like R*st.
Silicon allows developens to create their own custom allocator, like Zig, as well as custom GC implementations that work natively.
Silicon uses @
prepended to all keywords for a very good reason. There will never be conflicts with new keywords added to the language.
This allows embedding DSLs, possibly ones created with Macros, within an Silicon program.
@let UserQuery = ```sql
SELECT *
FROM users
WHERE id = ${user.id}
```
Macros use the @@
sigil. Macros is Silicon are extremely powerful. Macros can be used to create whole new language features and syntax. This is NOT encouraged but for niche applications and mostly for incremental bootstrapping new language features.
Silicon encourages function composition so there is a dedicated pipe operator, |>
.
# setup
@fn plusOne:int n:int = n + 1;
@let age = 32;
# function call
&plusOne age // 33
# pipe
age |> plusOne // 33
Silicon allows negative indexing into all iterables. There are also head
and tail
methods to get the index item starting from the beginning or the end.
// function syntax
#head array 0
#tail array 0
// method syntax
(array.head 0)
(array.tail 0)
..
defines a range or series. A range
is definite while a series
is infinite. Ranges have a final value to calculate to 0..100
is 0 to 100 (inclusive if possible). A step may be added via a middle value 0..2..100
will count by 2's. 0..3..100
will only go to 99. 0..2..
will count by 2's indefinitely. [0..2..].get(50)
will return 100
.
a range / series of type T is define like so
[T..]
// Define infinite series of even integers
@let evens:[int..] = 2..4..
// treat it like a normal array
evens.get(10) // 20
evens(10) // 20
(evens 10) // 20
Like Ruby, Silicon
has both internal and external iterators.
@exit
return / break from current scope
@yeet
return from parent scope (non-local return like Ruby and Smalltalk)
@give
yield value
Internal iterators are preferred but most languages don't have any way to express returning early from them. Silicon
does! @yeet
Silicon has it AND it lets you mix declaration when doing it.
@let first_name
first_name, @let last_name = $(first_name = "Nate", last_name = "Hedglin)
Silicon doesn't have a new
keyword because that would be confusing. We aren't heap allocating.
This will require more thinking
Silicon just calls them interchangeably. How they behave depend how they are declared. In C++ pointers can be reassigned while reference cannot. In silicon ->
is just a pointer. @ref
is by default a reference but @mut @ref
is a mutable reference, maybe that could just be @ptr
instead?
Reference automatically dereference themselves, which is convient for most development but I also like C's explicit data->field
syntax.
My idea of modes
comes from Jonathan Goodwin's paper, "A Framework for Gradual Memory Management". This has become very popular, especially since Crablang aka R*st has become so popular.
This won't be implemented until V2 but Silicon will start taking the locality
approach that JaneStreet took with Oxidizing OCaml.
Silicon will have true generics like C#
.
Silicon's goal for syntax is to be similar to C but cleaner like Go i.e. no parens. One issue though is that List<T>
syntax messed with LSPs because HTML uses <>
as well. So I want a cleaner syntax. List:T
or List:(T)
C#
var map = new Dict<int,string>();
var map = new Dict<Dict<int,bool>,string>();
Si
@let ['T] genericAdd:T a:T,b:T = { a + b }
@let ['T] genericAdd:T a:T,b:T = { a + b }
Just use backticks like Javascript
@let word = "interpolation"
`multi-line string
with ${word} support!`