SkillAgentSearch skills...

Mico

Mico ("Monkey" in catalan). Monkey language implementation done with C++. https://interpreterbook.com/

Install / Use

/learn @newenclave/Mico
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Mico

<a href="https://scan.coverity.com/projects/newenclave-mico"> <img alt="Coverity Scan Build Status" src="https://img.shields.io/coverity/scan/13291.svg"/> </a>

Monkey :monkey: the language interpreter implementation done with C++. https://interpreterbook.com/

  • There is no compiler implementation here. Sorry. But I dont have a piece of time for this :(
  • Feel free to ask me anything.
  • Now I'm a more experienced and would rewrite this code completely :)
  • thanks Thorsten Ball :)
  • https://monkeylang.org/

Old README

Mico REPL Terminal

Requirements

  • C++ compiler (c++11 or later)
  • The book https://interpreterbook.com/. If you have not read it yet.

Table of Contents

Compile

Mico is a header-only project. Well you need just compile mico.cpp

 github $ git clone https://github.com/newenclave/mico.git
 github $ cd mico
 mico $ git submodule update --init etool
 mico $ g++ -std=c++11  mico.cpp -O2 -Iinclude -Ietool/include -Wall -o mico

Or clang

 mico $ clang++ -O2 mico.cpp -std=c++11 -Iinclude -Ietool/include -Wall -o mico

Or MS SDK compiler. It should be called from the "Visual Studio Command Prompt" for example

mico> cl /I include /I etool/include mico.cpp
mico> link /OUT:"mico.exe" mico.obj

Or just use Visual Studio (at least version 12)

Thats all.

Monkey and Mico

"Mico" is an implementation but of course it has some difference. For now I'm pretty sure that Mico can run the major part of Monkey's code.

View

Mico supports: integers, floats, chars, strings, arrays, tables, functions, modules, intervals

    let int  = 1_000_000                     // int is an integer
    let f    = 0.1e-3                        // f is a float `0.0001`
    let s    = "This is a string"            // string
    let t    = { "x": 0, "y": 0, "z": 0 }    // table (or Hash)
    let a    = [1, 2, 3, 4, 5, 6, [0, 0, 0]] // array (that contains another array)
    let fun  = fn(a, b){ (a - b) * (a + b) } // function
    let mod  = module { let var1 = 1; let var2 = 2 } // module
    let ival = 1..100                                // interval
    let c    = '🐒'     // character

Identifiers

Identifiers can use unicode symbols

    let кирилица = "Кирилица"
    let españa   = "Spain"
    let 中國      = 12312
    let العربية
        = {1: 中國}

    io.puts(кирилица)
    io.puts(españa)
    io.puts(中國)
    io.puts(العربية
            [1])

    // Кирилица
    // Spain
    // 12312
    // 12312

Token position

Every token has its position.

    let test_val = someUnknownCall()
    error: [1:15] Identifier not found 'someUnknownCall'

Numbers

Numbers can contain a gap symbol _. The symbol can be included both in integers and in floats.

    let int = 1_000_000             // 1000000
    let hex = 0xAAA_BBB             // 11185083
    let bin = 0b1111_0000_1111_0000 // 61680
    let ter = 0t22_11_22_11         // 6232
    let oct = 0_777_111_222_333     // 68604470491
    let flt = 10.1000_0002          // 10.10000002

Strings

    let s = "string"
    io.puts(s[1])
    // `t`
    let s = "中國"
    io.puts(s, " ", len(s), " ", s[0])
    // `中國 2 中`

Yes. It supports the unicode. Not completely of course. I've written a small utf8 parser and I think it's enough for this toy language. And for Windows it uses native API for encoding.

Raw strings

Raw strings are just arrays of bytes

    let s = r"string"
    io.puts(s[1])
    // 116
    let s = r"中國"
    io.puts(s, " ", len(s), " ", s[0])
    // 中國 6 228

Unlike strings raw strings know nothing about the unicode. And that is why string 中國 has length 2 and the lenght of the raw string is 6.

Slices

Slice is a part of an array or a string. Slice holds the object (string or array) and an interval [left..right]. The slice can be created with index operator []. Interval includes only its left side (i.e. the intervals are left closed, right open). Full container interval can be created with the interval cont[0..len(cont)] or cont[0..-1] (see "Negative index" above)

    let str = "This is a string"
    let this = str[0..4]
    io.puts(this)
    // shows `This`

Arrays slices

    let arr = [0,1,2,3,4,5,6,7,8,9]
    let s = arr[0..3]
    for i in s { io.put( i, " " ) } // shows `0 1 2`

Slice can change its direction. If the left part of the interval is greater then right, interval changes its direction.

    let arr = [0,1,2,3,4,5,6,7,8,9]
    let s = arr[8..2]
    for i in s { io.put( i, " " ) } // shows `7 6 5 4 3 2`

Of cource it's only valid when an element is accessed by index

    let str = "Hello, world!"
    let s = str[len(str)..0]
    for i in s { io.put( i ) } // shows `!dlrow ,olleH`
    /// but!
    io.puts(s) // Hello, world!

Slices are not copyes!

Slice can be also created from another slice.

    let arr = [0,1,2,3,4,5,6,7,8,9]
    let s = arr[1..10] // s is a slice[1,2,3,4,5,6,7,8,9]
    let t = s[2..5]    // t is a slice[3, 4, 5]
    for i in t { io.put( i, " " ) } // shows `3 4 5`

Negative index

Elements of arrays or strings can be obtained by negative index. -1 means the last element of the array/string

    let arr = [0,1,2,3,4,5,6,7,8,9]
    io.puts(arr[-1]) // 9
    io.puts(arr[-2]) // 8
    let s = "中國"
    io.puts(s[-2]) // 中

Slices also can be created by adding a negative index

    let str = "Hello, world!Äáç¶"
    let sym = str[-5..-1]
    let hello = str[0..-5]
    io.puts(sym) // Äáç¶
    io.puts(hello) // Hello, world!

Mutability

By-default all values set by let statement are inmutable. For making a variable, that can change its value use var statement. Every variable is a real variable and can be changed by assignmet operator =.

    var a = [1, 2, 3, 4, 6]
    var b = 1
    let d = 77.77 // `d` is constant
    b = 10        // ok
    c = 100       // oops; error: [1:0] Identifier not found: 'c'
    d = 88.88     // oops; error: [1:2] Invalid left value for ASSIGN d

    let fun = fn( ) {
        let a = 100 // here `a` shadows the variable `a` from the global scope
        b = 0.0     // here `b` is from the global scope
    }
    fun( )

mut keyword

All objects are also constats. It can be changed by keyword mut. It makes sense for arrays and tables.

    let a = [1,2,3,4]
    a[0] = 1000
    // error: [2:5] Invalid left value for ASSIGN a[0]
    // as far as the object is const
    let a = mut [1,2,3,4]
    a[0] = 1000     // ok
    io.puts(a[0])   // shows `1000`

const keyword

The const keyword can make an object constant.

    let a = mut [1,2,3,4]
    a[0] = 1000     // ok
    let a = const a // set const
    a[0] = 1000
    // error: [1:5] Invalid left value for ASSIGN a[0]

The keywords mut and const always make a copy of the object if the mutablity of the object is different.

    let a = mut [1,2,3,4]
    let a = mut a       // returns `a` without changes
    let a = const a     // makes a copy of `a`

The operator is a right arm operator.

    var a = [1, 2, 3, 4, 5]
    a[0] = a[1] = a[2] = a[3] = a[4] = 0
    // a == [0, 0, 0, 0, 0]

The let statement makes constants objects

    let a = [1, 2, 3, 4, 5]
    a[0] = a[1] = a[2] = a[3] = a[4] = 0
    // error: [2:9] Invalid left value for ASSIGN a[0]

Intervals

Intervals are pairs of values. Values can be integers, floats, strings or boolean. Operator .. creates an interval. For now there are not a lot of operations with intervals.

    let float   = 1.0..100.0
    let int     = 1..100
    let bool    = false..true
    let strings = "a".."z"

for in

The operator makes a for-loop. It's an expression and always returns its value as the result. There are several types of the operator.

Simple counter loop. Accepts an integer or a float as a value and makes a loop that is repeated value times

    for i in 10 {
        io.put(i, " ")
    }
    io.puts( )

This code shows 0 1 2 3 4 5 6 7 8 9.

The operator can have a step value that can change loop's increment and even make it negative

    for i in 10, 2 {
        io.put(i, " ")
    }
    io.puts( )
    // 0 2 4 6 8

    for i in -7, -0.7 {
        io.put(i, " ")
    }
    io.puts( )
    // 0 -0.7 -1.4 -2.1 -2.8 -3.5 -4.2 -4.9 -5.6 -6.3

An interval loop acccepts a numeric (float or integer) interval and

Related Skills

View on GitHub
GitHub Stars38
CategoryDevelopment
Updated3mo ago
Forks6

Languages

C++

Security Score

92/100

Audited on Dec 9, 2025

No findings