Git Product home page Git Product logo

rune's Introduction

ᚣ The Rune Programming Language

A faster, safer, and more productive systems programming language

This is not an officially supported Google product.

NOTE: Rune is an unfinished language. Feel free to kick tires and evaluate the cool new security and efficiency features of Rune, but, for now, it is not recommended for any production use case.

What is Rune?

Rune is a Python-inspired efficient systems programming language designed to interact well with C and C++ libraries. Rune has many security features such as memory safety, and constant-time processing of secrets. Rune aims to be faster than C++ for most memory-intensive applications, due to its Structure-of-Array (SoA) memory management.

It provides many of its features by deeply integrating features similar to the "DataDraw" tool into the primitives and constructs of the language. DataDraw is a code-generation tool that generates highly-optimized C code which outperforms e.g., the C++ STL given a declarative description of data-structures and relationships between them. For more information, see the DataDraw 3.0 Manual.

Additional documentation:

Rune in Action

Let's take a look at two examples that showcase many of the unique features of Rune:

  1. A simple example of a secret type, and how it can be used to protect against timing attacks.
  2. A more complex example of a data-structure with nullable, self-referential recursive references.
    • (This can present footguns in many languages, but it is trivial in Rune)

Dedicated "secret" types

Consider the following example for treatment of secrets:

// Check the MAC (message authentication code) for a message.  A MAC is derived
// from a hash over the `macSecret` and message.  It ensures the message has not
// been modified, and was sent by someone who knows `macSecret`.
func checkMac(macSecret: secret(string), message: string, mac: string) -> bool {
    computedMac = computeMac(macSecret, message)
    return mac == computedMac
}

func computeMac(macSecret: string, message: string) -> string {
  // A popular MAC algorithm.
  return hmacSha256(macSecret, message)
}

Can you see the potential security flaw? In most languages, an attacker with accurate timing data can forge a MAC on a message of their choice, causing a server to accept it as genuine.

Assume the attacker can tell how long it takes for mac == computedMac to run. If the first byte of an attacker-chosen mac is wrong for the attacker-chosen message, the loop terminates after just one comparison. With 256 attempts, the attacker can find the first byte of the expected MAC for the attacker-controlled message. Repeating this process, the attacker can forge an entire MAC.

Users of Rune are protected, because the compiler sees that macSecret is secret, and thus the result of hmacSha256 is secret. The string comparison operator, when either operand is secret, will run in constant time, revealing no timing information to the attacker. Care must still be taken in Rune, but many common mistakes like this are detected by the compiler, and either fixed or flagged as an error.

A "DB-embedded" language: relational data-structures and optimal memory-efficiency

As for the speed and safety of Rune's memory management, consider a simple Human class. This can be tricky to model in some languages, yet is trivial in both SQL and Rune.

class Human(self: Human, name: string, mother: Human? = null(self), father: Human? = null(self)) {
  self.name = name

  // The methods "appendMotheredHuman" and "appendFatheredHuman" are generated
  // by code "transformers", a key factor in Rune's performance.
  //
  // We'll learn more about these methods in the next section ("How does this work?").
  if !isnull(mother) {
    mother.appendMotheredHuman(self)
  }
  if !isnull(father) {
    father.appendFatheredHuman(self)
  }

  func printFamilyTree(self, level: u32) {
    for i in range(level) {
      print "    "
    }
    println self.name
    for child in self.motheredHumans() {
      child.printFamilyTree(level + 1)
    }
    for child in self.fatheredHumans() {
      child.printFamilyTree(level + 1)
    }
  }
}

// Relation statements are similar to "Foreign Key" constraints in SQL.
// They are used to define the relationships between data-structures.
//
// The "cascade" keyword means that when a Human is destroyed, all of
// its children are recursively destroyed.
// (In other words, manual invalidation of pointers is not required)
//
// This ability is also provided by code transformers.  See
// builtin/doublylinked.rn
relation DoublyLinked Human:"Mother" Human:"Mothered" cascade
relation DoublyLinked Human:"Father" Human:"Fathered" cascade

// Let's create a family tree.
adam = Human("Adam")
eve = Human("Eve")
cain = Human("Cain", eve, adam)
abel = Human("Abel", eve, adam)
alice = Human("Alice", eve, adam)
bob = Human ("Bob", eve, adam)
malory = Human("Malory", alice, abel)
abel.destroy()
adam.printFamilyTree(0u32)
eve.printFamilyTree(0u32)

When run, this prints:

Adam
    Cain
    Alice
    Bob
Eve
    Cain
    Alice
    Bob

How does this work?

Note that Abel and Malory are not listed. This is because we didn't just kill Abel, we destroyed Abel, and this caused all of Abel's children to be recursively destroyed. Also note that Rune now supports null safety. Null safety does not mean null does not exist in the language. It means types by default cannot be null. This can be overridden with <type>? in the type constraint.

Relation statements are similar to columns in SQL tables. A table with a Mother and Father column has two many-to-one relations in a database.

Relation statements give the Rune compiler critical hints for memory optimization. Objects which the compiler can prove are always in cascade-delete relationships do not need to be reference counted. The relation statements also inform the compiler to update Human's destructor to recursively destroy children. Rune programmers never write destructors, removing this footgun from the language.

To understand why Rune's generated SoA code is so efficient, consider the arrays of properties created for the Human example above:

nextFree = [null(Human)]
motherHuman = [null(Human)]
prevHumanMotheredHuman = [null(Human)]
nextHumanMotheredHuman = [null(Human)]
firstMotheredHuman = [null(Human)]
lastMotheredHuman = [null(Human)]
fatherHuman = [null(Human)]
prevHumanFatheredHuman = [null(Human)]
nextHumanFatheredHuman = [null(Human)]
firstFatheredHuman = [null(Human)]
lastFatheredHuman = [null(Human)]
name = [""]

A total of 12 arrays are allocated for the Human class in SoA memory layout. In printFamilyTree, we only access 5 of them. In AoS memory layout, all 12 fields would be loaded into cache during the tree traversal, and all fields would be 64 bits on a 64-bit machine. In Rune, only the string references are 64-bits by default. As a result, Rune loads only 25% as much data into cache during the traversal, improving memory load times, while simultaneously improving cache hit rates.

This is why Rune's binary_trees.rn code already runs faster than any other single-threaded result in the Benchmark Games. (Rune is not yet multi-threaded). The only close competitor is C++, where the author uses the little-known std::pmr::monotonic_buffer_resource class from the <memory_resource> library. Not only is Rune's SoA memory layout faster, but its solution is more generic: we can create/destroy Node objects arbitrarily, unlike the C++ benchmark based on std::pmr::monotonic_buffer_resource. When completed, we expect Rune to win most memory-intensive benchmarks.

Installation

Compiling the Rune compiler:

You'll need 6 dependencies installed to compile Rune:

  • Bison (parser generator)
  • Flex (lexer generator)
  • GNU multi-precision package gmp
  • Clang version 10
  • Datadraw, an SoA data-structure generator for C
  • CTTK, a constant-time big integer arithmetic library The first four can be installed with one command:
$ sudo apt-get install bison flex libgmp-dev clang clang-14

Installing Datadraw requires cloning the source from github.

$ git clone https://github.com/waywardgeek/datadraw.git
$ sudo apt-get install build-essential
$ cd datadraw
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

Hopefully that all goes well... After dependencies are installed, to build rune:

$ git clone https://github.com/google/rune.git
$ git clone https://github.com/pornin/CTTK.git
$ cp CTTK/inc/cttk.h CTTK
$ cd rune
$ make

CTTK was written by Thomas Pornin. It provides constant-time big-integer arithmetic.

If make succeeds, test the Rune compiler in the rune directory with:

$ ./runtests.sh

Some tests are currently expected to fail, but most should pass. To install rune under /usr/local/rune:

$ sudo make install

Test your installation:

$ echo 'println "Hello, World!"' > hello.rn
$ rune -g hello.rn
$ ./hello

You can debug your binary executable with gdb:

$ gdb ./hello

TODO: add instructions on how to debug the compiler itself, especially the datadraw debug functionality.

rune's People

Contributors

0dminnimda avatar alexpovel avatar anned20 avatar ctarnold avatar gavinray97 avatar mattn avatar minitauros avatar qeesung avatar roydigerhund avatar rurban avatar scolsen avatar waywardgeek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rune's Issues

Typo in the Readme

relation DoublyLinked Human:"Fater" Human:"Fathered" cascade

The Human is written Fater instead of Father

Doubly linked relation?

In the class example in the README, the Human class adds self to mother and father. However it does not add mother and father anywhere into self, which is what I would expect with "DoublyLinked." What does it mean?

Grammar railroad diagram

Using some online tools like https://www.bottlecaps.de/rr/ui and https://www.bottlecaps.de/convert/ and a bit of manual fixes we can have a nice navigable railroad diagram.

Copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui on the tab Edit Grammar the click on the tab View Diagram to see/download a navigable railroad diagram.

/* converted on Sun Nov 27, 2022, 10:23 (UTC+01) by bison-to-w3c v0.62 which is Copyright (c) 2011-2022 by Gunther Rademacher <[email protected]> */

goal     ::= initialize optNewlines runeFile
initialize
         ::=
runeFile ::= statements
statements
         ::= statement*
statement
         ::= appendCode
           | assertStatement
           | assignmentStatement
           | callStatement
           | class
           | debugStatement
           | enum
           | externFunction
           | finalFunction
           | foreachStatement
           | forStatement
           | function
           | generateStatement
           | generatorStatement
           | ifStatement
           | import
           | prependCode
           | printlnStatement
           | printStatement
           | refStatement
           | relationStatement
           | returnStatement
           | struct
           | switchStatement
           | throwStatement
           | unitTestStatement
           | unrefStatement
           | whileStatement
           | yield
import   ::= ( ( KWIMPORT | KWIMPORTLIB | KWIMPORTRPC ) pathExpressionWithAlias | KWUSE IDENT ) newlines
class    ::= ( classHeader | exportClassHeader ) '(' oneOrMoreParameters ')' block
classHeader
         ::= KWCLASS IDENT optWidth
optWidth ::= ( ':' UINTTYPE )?
exportClassHeader
         ::= ( KWEXPORT | KWEXPORTLIB | KWRPC ) KWCLASS IDENT optWidth
struct   ::= structHeader '{' newlines ( structMember newlines )* '}' newlines
           | exportStructHeader block
structHeader
         ::= KWSTRUCT IDENT
structMember
         ::= optConst IDENT optTypeExpression optInitializer
optConst ::= KWCONST?
optInitializer
         ::= ( '=' expression )?
exportStructHeader
         ::= ( KWEXPORT | KWEXPORTLIB ) KWSTRUCT IDENT
appendCode
         ::= appendCodeHeader block
appendCodeHeader
         ::= KWAPPENDCODE pathExpression?
prependCode
         ::= prependCodeHeader block
prependCodeHeader
         ::= KWPREPENDCODE pathExpression?
block    ::= '{' newlines statements '}' optNewlines
function ::= ( functionHeader | exportFunctionHeader | rpcHeader ) '(' parameters ')' optFuncTypeExpression block
functionHeader
         ::= ( KWFUNC | KWITERATOR ) IDENT
           | KWOPERATOR operator
operator ::= '+'
           | '-'
           | '*'
           | '/'
           | '%'
           | KWAND
           | KWOR
           | KWXOR
           | '&'
           | '|'
           | '@'
           | '^'
           | KWSHL
           | KWSHR
           | KWROTL
           | KWROTR
           | KWADDTRUNC
           | KWSUBTRUNC
           | KWMULTRUNC
           | '~'
           | '<'
           | KWLE
           | '>'
           | KWGE
           | KWEQUAL
           | KWNOTEQUAL
           | '!'
           | '[' ']'
           | KWIN
exportFunctionHeader
         ::= ( KWEXPORT ( KWFUNC | KWITERATOR ) | KWEXPORTLIB KWFUNC ) IDENT
parameters
         ::= oneOrMoreParameters?
oneOrMoreParameters
         ::= parameter ( ',' optNewlines parameter )*
parameter
         ::= optVar ( IDENT | '<' IDENT '>' ) optTypeExpression
           | initializedParameter
optVar   ::= KWVAR?
initializedParameter
         ::= optVar ( IDENT | '<' IDENT '>' ) optTypeExpression '=' expression
externFunction
         ::= ( KWEXTERN STRING functionHeader | rpcHeader ) '(' parameters ')' optFuncTypeExpression newlines
rpcHeader
         ::= KWRPC IDENT
ifStatement
         ::= ifPart elseIfPart* optElsePart
ifPart   ::= ifStatementHeader expression block
ifStatementHeader
         ::= KWIF
elseIfPart
         ::= elseIfStatementHeader expression block
elseIfStatementHeader
         ::= KWELSE KWIF
optElsePart
         ::= elsePart?
elsePart ::= elseStatementHeader block
elseStatementHeader
         ::= KWELSE
switchStatement
         ::= switchStatementHeader expression switchBlock
switchStatementHeader
         ::= KWSWITCH
switchBlock
         ::= '{' newlines switchCase* optDefaultCase '}' optNewlines
switchCase
         ::= KWCASE expression ( ',' optNewlines expression )* block
optDefaultCase
         ::= ( defaultCaseHeader block )?
defaultCaseHeader
         ::= KWDEFAULT
whileStatement
         ::= optDoStatement whileStatementHeader expression ( newlines | block )
whileStatementHeader
         ::= KWWHILE
optDoStatement
         ::= doStatement?
doStatement
         ::= doStatementHeader block
doStatementHeader
         ::= KWDO
forStatement
         ::= forStatementHeader nonConstAssignmentExpression ',' optNewlines expression ',' optNewlines nonConstAssignmentExpression block
forStatementHeader
         ::= KWFOR
assignmentStatement
         ::= assignmentExpression newlines
assignmentExpression
         ::= KWCONST? nonConstAssignmentExpression
nonConstAssignmentExpression
         ::= accessExpression optTypeExpression assignmentOp expression
assignmentOp
         ::= '='
           | KWADDEQUALS
           | KWSUBEQUALS
           | KWMULEQUALS
           | KWDIVEQUALS
           | KWMODEQUALS
           | KWBITANDEQUALS
           | KWBITOREQUALS
           | KWBITXOREQUALS
           | KWANDEQUALS
           | KWOREQUALS
           | KWXOREQUALS
           | KWEXPEQUALS
           | KWSHLEQUALS
           | KWSHREQUALS
           | KWROTLEQUALS
           | KWROTREQUALS
           | KWADDTRUNCEQUALS
           | KWSUBTRUNCEQUALS
           | KWMULTRUNCEQUALS
optTypeExpression
         ::= ( ':' expression )?
optFuncTypeExpression
         ::= ( KWARROW expression )?
accessExpression
         ::= tokenExpression ( '(' callParameterList ')' | '.' IDENT | '[' expression ( ':' expression )? ']' )*
callStatement
         ::= accessExpression '(' callParameterList ')' newlines
callParameterList
         ::= ( callParameter ( ',' optNewlines callParameter )* optComma )?
callParameter
         ::= ( IDENT '=' )? expression
optComma ::= ','?
printStatement
         ::= KWPRINT expressionList newlines
printlnStatement
         ::= KWPRINTLN expressionList newlines
throwStatement
         ::= KWTHROW expressionList newlines
assertStatement
         ::= KWASSERT expressionList newlines
returnStatement
         ::= KWRETURN expression? newlines
generatorStatement
         ::= generatorHeader '(' parameters ')' block
generatorHeader
         ::= KWGENERATOR IDENT
generateStatement
         ::= KWGENERATE pathExpression '(' expressionList ')' newlines
relationStatement
         ::= KWRELATION pathExpression pathExpression optLabel pathExpression optLabel optCascade optExpressionList newlines
optLabel ::= ( ':' STRING )?
optCascade
         ::= KWCASCADE?
optExpressionList
         ::= ( '(' expressionList ')' )?
yield    ::= KWYIELD expression newlines
unitTestStatement
         ::= unitTestHeader block
unitTestHeader
         ::= KWUNITTEST IDENT
debugStatement
         ::= debugHeader block
debugHeader
         ::= KWDEBUG
enum     ::= enumHeader '{' newlines entry+ '}' newlines
enumHeader
         ::= KWENUM IDENT
entry    ::= IDENT ( '=' INTEGER )? newlines
foreachStatement
         ::= forStatementHeader IDENT KWIN expression block
finalFunction
         ::= finalHeader '(' parameter ')' block
finalHeader
         ::= KWFINAL
refStatement
         ::= KWREF expression newlines
unrefStatement
         ::= KWUNREF expression newlines
expressionList
         ::= oneOrMoreExpressions?
oneOrMoreExpressions
         ::= expression ( ',' optNewlines expression )*
expression
         ::= dotDotDotExpression
dotDotDotExpression
         ::= selectExpression ( KWDOTDOTDOT selectExpression )?
selectExpression
         ::= orExpression ( '?' orExpression ':' orExpression )?
orExpression
         ::= xorExpression ( KWOR xorExpression )*
xorExpression
         ::= andExpression ( KWXOR andExpression )*
andExpression
         ::= inExpression ( KWAND inExpression )*
inExpression
         ::= modExpression ( KWIN modExpression )?
modExpression
         ::= relationExpression ( KWMOD bitorExpression )?
relationExpression
         ::= bitorExpression ( ( '<' | KWLE | '>' | KWGE | KWEQUAL | KWNOTEQUAL ) bitorExpression )?
bitorExpression
         ::= bitxorExpression ( '|' bitxorExpression )*
bitxorExpression
         ::= bitandExpression ( '@' bitandExpression )*
bitandExpression
         ::= shiftExpression ( '&' shiftExpression )*
shiftExpression
         ::= addExpression ( ( KWSHL | KWSHR | KWROTL | KWROTR ) addExpression )?
addExpression
         ::= KWSUBTRUNC? mulExpression ( ( '+' | '-' | KWADDTRUNC | KWSUBTRUNC ) mulExpression )*
mulExpression
         ::= prefixExpression ( ( '*' | '/' | '%' | KWMULTRUNC ) prefixExpression )*
prefixExpression
         ::= postfixExpression ( '^' postfixExpression )*
           | ( '!' | '~' | '-' | ( '<' | KWCASTTRUNC ) prefixExpression '>' ) prefixExpression
postfixExpression
         ::= accessExpression
           | '&' pathExpression '(' expressionList ')'
tokenExpression
         ::= IDENT
           | STRING
           | INTEGER
           | FLOAT
           | RANDUINT
           | BOOL
           | '[' oneOrMoreExpressions ']'
           | ( KWSECRET | KWREVEAL | KWARRAYOF | KWTYPEOF | KWUNSIGNED | KWSIGNED | KWWIDTHOF | KWISNULL )? '(' expression ')'
           | tupleExpression
           | KWNULL
           | typeLiteral
typeLiteral
         ::= UINTTYPE
           | INTTYPE
           | KWSTRING
           | KWBOOL
           | KWF32
           | KWF64
pathExpression
         ::= IDENT ( '.' IDENT )*
pathExpressionWithAlias
         ::= pathExpression ( KWAS IDENT )?
tupleExpression
         ::= '(' expression ( ( ',' optNewlines expression )+ optComma | ',' ) ')'
optNewlines
         ::= '\n'*
newlines ::= ( '\n' | ';' )+

//
// Tokens
//

// <INITIAL>\("[^"]+"\)\s+{.+?return \([^;]+\); }  -> \2 ::= \1

KWAPPENDCODE ::= "appendcode"
KWARRAYOF ::= "arrayof"
KWAS ::= "as"
KWASSERT ::= "assert"
KWBOOL ::= "bool"
KWCASCADE ::= "cascade"
KWCASE ::= "case"
KWCLASS ::= "class"
KWCONST ::= "const"
KWDEBUG ::= "debug"
KWDEFAULT ::= "default"
KWDO ::= "do"
KWELSE ::= "else"
KWENUM ::= "enum"
KWEXPORT ::= "export"
KWEXPORTLIB ::= "exportlib"
KWRPC ::= "rpc"
KWEXTERN ::= "extern"
BOOL ::= "false"
KWFINAL ::= "final"
KWFOR ::= "for"
KWFUNC ::= "func"
KWGENERATE ::= "generate"
KWGENERATOR ::= "generator"
KWIF ::= "if"
KWIMPORT ::= "import"
KWIMPORTLIB ::= "importlib"
KWIMPORTRPC ::= "importrpc"
KWIN ::= "in"
KWISNULL ::= "isnull"
KWITERATOR ::= "iterator"
KWMOD ::= "mod"
KWNULL ::= "null"
KWOPERATOR ::= "operator"
KWPREPENDCODE ::= "prependcode"
KWPRINT ::= "print"
KWPRINTLN ::= "println"
KWREF ::= "ref"
KWRELATION ::= "relation"
KWRETURN ::= "return"
KWREVEAL ::= "reveal"
KWSECRET ::= "secret"
KWSIGNED ::= "signed"
KWSTRING ::= "string"
KWSTRUCT ::= ("struct"|"message")
KWSWITCH ::= "switch"
KWTHROW ::= "throw"
BOOL ::= "true"
KWTYPEOF ::= "typeof"
KWUNITTEST ::= "unittest"
KWUNREF ::= "unref"
KWUNSIGNED ::= "unsigned"
KWUSE ::= "use"
KWVAR ::= "var"
KWWHILE ::= "while"
KWWIDTHOF ::= "widthof"
KWYIELD ::= "yield"

KWADDEQUALS ::= "+="
KWADDTRUNCEQUALS ::= "!+="
KWADDTRUNC ::= "!+"
KWANDEQUALS ::= "&&="
KWBITANDEQUALS ::= "&="
KWAND ::= "&&"
KWARROW ::= "->"
KWCASTTRUNC ::= "!<"
KWDIVEQUALS ::= "/="
KWDOTDOTDOT ::= "..."
KWEQUAL ::= "=="
KWEXPEQUALS ::= "^="
KWGE ::= ">="
KWLE ::= "<="
KWMODEQUALS ::= "%="
KWMULEQUALS ::= "*="
KWMULTRUNCEQUALS ::= "!*="
KWMULTRUNC ::= "!*"
KWNOTEQUAL ::= "!="
KWBITOREQUALS ::= "|="
KWOREQUALS ::= "||="
KWOR ::= "||"
KWROTLEQUALS ::= "<<<="
KWROTL ::= "<<<"
KWROTREQUALS ::= ">>>="
KWROTR ::= ">>>"
KWSHLEQUALS ::= "<<="
KWSHL ::= "<<"
KWSHREQUALS ::= ">>="
KWSHR ::= ">>"
KWSUBEQUALS ::= "-="
KWSUBTRUNCEQUALS ::= "!-="
KWSUBTRUNC ::= "!-"
KWBITXOREQUALS ::= "@="
KWXOREQUALS ::= "@@="
KWXOR ::= "@@"
KWF32 ::= "f32"
KWF64 ::= "f64"

invalid trunc should throw

errortests/trunc.rn fails with a var (and also a constant)

variable should add a runtime truncation check:

%2 = trunc i64 %1 to i16, !dbg !208
; missing %1 vs %2 check

constant may throw directly at compile-time:

println "%x16" % <u16>0xdeadbeef =>
%1 = trunc i64 3735928559 to i16, !dbg !205
diff --git llvm/genllvm.c llvm/genllvm.c
index a9fff61..245cb0d 100644
--- llvm/genllvm.c
+++ llvm/genllvm.c
@@ -1490,6 +1490,8 @@ static llElement resizeSmallInteger(llElement element, uint32 newWidth, bool isS
   char *operation;
   if (newWidth < oldWidth) {
     operation = "trunc";
+    //TODO if constant throw error if truncation looses info.
+    //     else if not constant add code to check at run-time.
   } else {
     deDatatypeType type = deDatatypeGetType(oldDatatype);
     if (type == DE_TYPE_INT) {

See also: https://cwe.mitre.org/data/definitions/197.html

Relevance to Nim

This looks a hell lot like an already existing language, called Nim

Python like syntax with C/C++ interop, reference counting and so on.

Did you take any inspiration?
https://nim-lang.org/

And what would you say, are Rune's benefits, compared to it?

Probably missing dependency during installation

Following the installation instructions in the README, during the "building rune"-step, I ran into a missing prerequisite. The make command in

$ git clone https://github.com/google/rune.git
$ git clone https://github.com/pornin/CTTK.git
$ cp CTTK/inc/cttk.h CTTK
$ cd rune
$ make

resulted in

clang -Wall -g -std=c11 -Wno-varargs -I../../CTTK -DRN_DEBUG -c array.c bigint.c io.c random.c
make[1]: clang: No such file or directory

This was off course easy fixable by installing clang. But since especially clang-14 is specifically stated as prerequisite I wondered if this list is incomplete and clang should be added to the instructions, specifically expanding

$ sudo apt-get install bison flex libgmp-dev clang-14

to

$ sudo apt-get install bison flex libgmp-dev clang clang-14

or if this was a problem on my site. Happy to give further information or to extend the README.

[SUP] hashValues fails to compile

I followed the "Compiling the Rune compiler" from the readme and it all finally compiled and didn't complain😅
Then I tried to run the tests and saw

/tmp/nullindirection-c4ad80.o: In function `hashValues':
/projects/rune/builtin/hashed.rn:17: undefined reference to `llvm.fshr.i64'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
./runl: line 6: ./errortests/nullindirection: No such file or directory
....
Passed: 39
Failed: 185

I tried to compile a hello world program I got the same error
Also I found that by using -b flag program was able to compile


  • rune: Current main
  • os: Ubuntu 18.04.5 LTS bionic on Windows 10 x86_64
  • clang: version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
    Target: x86_64-pc-linux-gnu
    Thread model: posix
    InstalledDir: /usr/bin

Fixed-size array allocation and fixed-size types

I see there is a method allocArrayBuffer in the runtime, but looking through every test in /tests and /newtests, I couldn't find some usage of code like:

std::byte buffer[4096];

I tried the below on a guess, but this was not valid rune:

myArray = [u32; 4096]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.