⚛️Intrinsics

This page will cover how you can contribute new intrinsic libraries or globals to Cosmo.

First, let me define what I mean when I say "intrinsic". I am referring to anything that is available to Cosmo without having to install a package. For example: the puts and gets functions are global intrinsics, and the HTTP and System libraries are imported intrinsics.

Written in Cosmo

If you want to write any code in Cosmo that will be intrinsic to Cosmo, just create a new Cosmo file in libraries/ and code away. Each file in libraries/ becomes an importable, except for global.⭐, which is injected into the global scope. When creating an importable intrinsic in Cosmo, the name to import will be the file name without the extension. For example: if I created libraries/colors.⭐, it would be importable via colors.

use * from "colors"

Written in Crystal

If you want to define Cosmo intrinsics that rely on Crystal to run (or are performance intensive), you can refer to src/cosmo/runtime/intrinsic. There are two types of intrinsics you can create via Cosmo's Crystal API: Libs, and IFunctions.

Intrinsic::Lib

A Lib is just a table behind the scenes, and holds associated IFunctions or other values. It contains an inject method which assigns any associated values into the scope.

The FileLib#inject method

As you can see, it defines a hash called file and assigns all of the File library's functions into it. It then assigns the file hash to the name File in the scope.

Intrinsic::IFunction

An IFunction is just a regular function, just without a body node. They are called like normal functions, besides having to interpret the function body. Arity checks are done just like normal functions as well. The below example of an IFunction (taken from Math::atan) has an arity of 1, meaning that it will throw if any more or any less arguments are provided. It also uses the TypeChecker#assert method to make sure the input is a float or an integer.

Declaring/Importing

Intrinsics written in Cosmo are not importable OR in the global scope by default. To finally implement your intrinsic, navigate to the Interpreter#declare_globals method. Each call to declare_intrinsic declares it as global. To make it importable, call the importable method. The first argument to the importable method is the name that it will be importable by. So for example, importing MathLib would look like:

use sin, cos, π from "math"

Last updated