Skip to content

Commit

Permalink
Add Lutin lexer (#1307)
Browse files Browse the repository at this point in the history
This commit adds a lexer for the Lutin language.
  • Loading branch information
jahierwan authored and pyrmont committed Sep 3, 2019
1 parent 9724e00 commit fd82b9c
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lib/rouge/demos/lutin
@@ -0,0 +1,18 @@
node gen_x_v1() returns (x:real) = loop 0.0<x and x<42.0

node gen_x_v2() returns (x:real) =
loop { 0.0<x and x<42.0 fby loop [20] x = pre x }

node gen_x_v3() returns (target:real; x:real=0.0) =
run target := gen_x_v2() in
loop { x = (pre x + target) / 2.0 }

let inertia=0.6

node gen_x_v4() returns (target:real; x:real=0.0) =
run target := gen_x_v2() in
exist px,ppx : real = 0.0 in
loop {
px = pre x and ppx = pre px and
x = (px+target) / 2.0+inertia*(px-ppx)
}
33 changes: 33 additions & 0 deletions lib/rouge/lexers/lutin.rb
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
#
# adapted from lustre.rf (adapted from ocaml.rb), hence some ocaml-ism migth remains
module Rouge
module Lexers
load_lexer 'lustre.rb'

class Lutin < Lustre
title "Lutin"
desc 'The Lutin programming language (Verimag)'
tag 'lutin'
filenames '*.lut'
mimetypes 'text/x-lutin'

def self.keywords
@keywords ||= Set.new %w(
let in node extern system returns weak strong assert raise try catch
trap do exist erun run type ref exception include false true
)
end

def self.word_operators
@word_operators ||= Set.new %w(
div and xor mod or not nor if then else pre)
end

def self.primitives
@primitives ||= Set.new %w(int real bool trace loop fby)
end
end
end
end
18 changes: 18 additions & 0 deletions spec/lexers/lutin_spec.rb
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

describe Rouge::Lexers::Lutin do
let(:subject) { Rouge::Lexers::Lutin.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'foo.lut'
end

it 'guesses by mimetype' do
assert_guess :mimetype => 'text/x-lutin'
end
end
end
64 changes: 64 additions & 0 deletions spec/visual/samples/lutin
@@ -0,0 +1,64 @@
-- A simple node
node gen_x_v2() returns (x:real) =
loop { 0.0<x and x<42.0 fby loop [20] x = pre x }

-- Using run
node up_and_down(min, max, delta:real) returns (x:real) =
Between(x, min, max)
fby
loop
exist lmin, lmax, ldelta : real in
run lmin := between(min, pre x) in
run lmax := between(pre x, max) in
run ldelta := between(0., delta) in
{
| run x := up(pre x, ldelta) in loop { x < lmax }
| run x := down(pre x, ldelta) in loop { x > lmin }
}

-- Prioritary choice
node env2(Speed,Roof_Speed:real) returns(
Start,Parked,Rot,Tick,OnOff,Done:bool; Dist:real) =
{
loop { not (OnOff and Start) } -- H1
&> loop { Parked => not Rot } -- H2
&> true fby loop {
( Speed > 0.0 => not Parked ) -- H3
and ( Roof_Speed > 0.0 => not Done ) -- H4
}
}

-- Weigths
let geneRotTick(Start, Rot, Tick,Danger:bool) : trace =
let accel = {{ | 1: not Rot | 5: Rot } &> { | 5: not Tick | 1: Tick } &>
Start &> not Danger }
in
let decel = {{ | 5: not Rot | 1: Rot } &> { | 1: not Tick | 5: Tick } } in
let stop = not Rot and Tick in
loop [50] not Rot fby
loop { loop [0,300] accel fby
loop [0,300] decel fby
loop [60,300] stop
}

-- Macros with trace
let OnceBefore(condition,event:bool) : trace =
loop { not (event and condition)} fby
event and condition

let when(condition:bool; BODY:trace) : trace =
loop {
| assert condition in BODY
| not condition
}

let IfThenElse(condition:bool;THEN,ELSE: trace) : trace = {
|> { condition &> THEN }
|> ELSE
}

node test_when(condition:bool) returns (res:int) =
when(condition, integers(0,res))

node test_IfThenElse(condition:bool) returns (res:int) =
IfThenElse(condition, integers(0,res), integers(-100,res))

0 comments on commit fd82b9c

Please sign in to comment.