Skip to content
This repository has been archived by the owner on Aug 13, 2023. It is now read-only.
/ cozy Public archive

Simple interpreted programming language for similar use-cases as Python and Node. Meant to be `cozy` no matter what languages you already know.

License

Notifications You must be signed in to change notification settings

zacanger/cozy

Repository files navigation

cozy

Abandoned

This was a fun project to help me learn more about PLD and Go, but I don't really have much time for it or interest in it anymore. You are more than welcome to fork it, or check out ABS which accomplishes many of the same goals and has an active developer community.


Simple interpreted programming language for similar use-cases as Python and Node. Meant to be cozy no matter what languages you already know.


This is a WIP. See the TODO.

Support with PayPal Patreon ko-fi

cozy (always spelled all-lowercase) is a simple, medium-to-high-level, interpreted, general purpose programming language. It can be used for many of the same tasks as shell scripts, Python, Node, and Ruby. It's dynamically and strongly typed, with some with features that work well with pseudo-functional programming but C-language-family syntax. There are no OOP constructs like classes; instead we have first-class functions, closures, plain data structures, and file-based modules.

It's meant to feel comfortable and familiar no matter what languages you might already know (hence the name). Performance isn't an explicit goal, but cozy is fairly fast (time the examples and try a benchmarking tool against the http server if you're curious). It's also meant to have a relatively simple host-language implementation (for example, much of the standard libarary is written in cozy itself) to make debugging easy and porting to other host languages in the future straightforward.

Example

# contrived example to show off some features and syntax; see the ./examples
# directory for more.
# reduce is a built-in method on arrays, int? is a built-in type checking
# function, and sum is a built-in method on arrays, but this example shows
# how they might be implemented by a user.

# let is for immutable variables
let reduce = fn (fun, xs, init) {
    # mutable is only available within blocks, not at at the top level
    mutable acc = init

    foreach i, x in xs {
        acc = fun(x, acc, i)
    }

    return acc
}

# identifiers can have unicode (for example, chinese characters),
# and question marks
let ints? = fn (xs) {
    foreach x in xs {
        # util is a builtin module
        if util.type(x) != "integer" && util.type(x) != "float" {
            return false
        }
    }

    # returns can be implicit (without the `return` keyword)
    true
}

let sum = fn (xs) {
    # basic assertions and a TAP-producing test library are built in
    util.assert(ints?(xs), "expected only numbers!")
    return reduce(
        fn (x, acc) {
            return x + acc
        }, xs, 0)
}

# only one level of equality checking, unlike JS's == vs ===
print(sum([1, 2, 3, 4]) == 10) # true

For more examples and documentation, see the examples and stdlib directories. The examples also serve as a second test suite. For vim, CLOC, and Ctags support, see the editor directory. Screenshot in vim:

vim plugin

About

Originally designed by writing a bunch of examples and a small stdlib. Implementation started as a fork from skx's version of the language from the Go Interpreters Book, and also includes some pieces of prologic's upstream version and ABS, among others (see comments). The differences between cozy and Monkey are too numerous to list here; it's best to think of it as a totally separate language. It's written in pure Go with minimal third-party dependencies, with a large amount of the standard library implemented in cozy itself.

This is the first large Go program I've worked on, so contributions, especially in areas where I didn't write idiomatic Go, are definitely welcome. See CONTRIBUTING for contribution guidelines.

Usage

Clone the repo and run make, and either copy the binary to somewhere in your path or run make install. Write some code (see the examples), and run cozy ./your-code.cz. You can also run without a specified file, in which case your entered code will be evaluated when you exit with ctrl+d.

Important Notes

  • print adds an ending newline, use or sys.STDOUT/sys.STDERR for raw text
  • No undefined or uninitialized variables Comments are Python/Shell style Errors
  • are values, so you can pass them around and use panic (like in Go) Using
  • set and delete on hashes returns a new hash let is for immutable
  • variables; mutable is for mutable ones; this is because setting mutable variables should be more annoying to do than setting mutable ones.
  • Uses Go's GC; porting to a different language might require writing a new GC.
  • Semicolons are optional Most statements are expressions, including if/else;
  • this also means implicit returns (without the return keyword) are possible
  • No top level mutable variables, because all top level variables are exported
  • Parens and braces are optional in for, foreach, and if expressions, as long as what would be between them is only one expression (would normally be typed on one line)
  • No ternary expressions, switch statements, or pattern matching; if statements are expressions and type-checking is dynamic, so there's no need for extra keywords or syntax
  • REPL history is stored at $HOME/.cozy_history, and the size (in lines) can be configured with the env var COZY_HISTSIZE
  • REPL config is stored at $HOME/.cozy_init and can contain any valid cozy code

Builtins

Global functions:

  • error creates a new error object
  • import imports another cozy file as a module
  • panic prints an error contents and exits
  • print Write values to STDOUT with newlines

Builtin modules (see examples for docs):

  • core
  • fs
  • http
  • json
  • math
  • net
  • sys
  • time
  • util

See also the standard library (written mostly in cozy itself).

Code Style

cozy doesn't care about formatting. You can use two spaces, four spaces, seventeen spaces, three spaces and a tab, or whatever. Semicolons are also optional in most cases (similar to the rules in JavaScript), and parenthesis and curly braces are also optional in conditions and loops.

The semi-official style which should be followed when submitting changes is fairly obvious from the examples and standard library:

  • Four spaces to indent
  • Use a space between identifiers and operators, with the exception of mutating postfix operators
  • Use a space between the fn keyword and opening paren
  • Use a space between opening/closing parens and opening/closing braces
  • Docstrings should be at the top of the function
  • Imports should be at the top of the module
  • Line length should not exceed 80 characters
  • Semicolons should not be used except in ambiguous situations
  • Identifiers should use snake_case

License

This code is licensed MIT. I've used code from various Monkey implementations, which are usually licensed MIT. Other code used in cozy includes comments with notes on the licenses.

About

Simple interpreted programming language for similar use-cases as Python and Node. Meant to be `cozy` no matter what languages you already know.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages