Skip to content

Latest commit

 

History

History
194 lines (117 loc) · 5.61 KB

advanced.md

File metadata and controls

194 lines (117 loc) · 5.61 KB

ADVANCED

Opaque and Pointer Types

Opaque

The Opaque type is used for extern types like for interoping with C or environment provided APIs.

Pointers

-> 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.

this, traits, interfaces

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.

Trait aka Interface

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
            @
        )
    @

Traits

// TODO: likely just add an @alias keyword

Modes aka Dialects

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.

Custom Allocators & GC

Silicon allows developens to create their own custom allocator, like Zig, as well as custom GC implementations that work natively.

Keywords

Silicon uses @ prepended to all keywords for a very good reason. There will never be conflicts with new keywords added to the language.

Quasi-Quotes

This allows embedding DSLs, possibly ones created with Macros, within an Silicon program.

    @let UserQuery = ```sql
        SELECT *
        FROM users
        WHERE id = ${user.id}
    ```

Macros

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.

Pipes

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

Negative Indexing

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)

Range / Series

.. 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

Interators

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

Non-Local Return

Internal iterators are preferred but most languages don't have any way to express returning early from them. Silicon does! @yeet

Destructuring

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.

Pointer vs Reference

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.

Locality, Modes, Oxidizing Silicon (Silica / Quartz)

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.

Generics

Silicon will have true generics like C#.

Syntax

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 }

Multi-line strings

Just use backticks like Javascript

@let word = "interpolation"

`multi-line string
with ${word} support!`