2018-12-01 21:06:12 +00:00
|
|
|
#lang racket/gui
|
|
|
|
|
2018-12-02 17:05:50 +00:00
|
|
|
(require "interpreter.rkt"
|
2018-12-03 19:58:43 +00:00
|
|
|
framework
|
|
|
|
racket/set)
|
2018-12-01 21:06:12 +00:00
|
|
|
|
|
|
|
; The editor width in pixels
|
|
|
|
(define EDITOR-WIDTH 600)
|
|
|
|
(define EDITOR-HEIGHT 600)
|
|
|
|
|
|
|
|
; The frame racket/gui base object for the editor
|
|
|
|
(define f (new frame%
|
|
|
|
[label "DrBrainf*ck"]
|
|
|
|
[width EDITOR-WIDTH]
|
|
|
|
[height EDITOR-HEIGHT]))
|
|
|
|
|
2018-12-04 09:28:34 +00:00
|
|
|
; execute-content: ((ProgState) -> Any) -> ProgState
|
|
|
|
; Given a callback, calls the callback with the last state of execution of the
|
|
|
|
; program loaded in the editor
|
|
|
|
(define (execute-content done)
|
2018-12-01 21:06:12 +00:00
|
|
|
(execute
|
2018-12-02 17:05:50 +00:00
|
|
|
(program->prog-state
|
2018-12-01 21:06:12 +00:00
|
|
|
(string->program
|
2018-12-04 09:28:34 +00:00
|
|
|
(send editor get-flattened-text)))
|
|
|
|
done (lambda (callback) (callback 50))))
|
2018-12-01 21:06:12 +00:00
|
|
|
|
2018-12-03 19:58:43 +00:00
|
|
|
; run-program: Button ControlEvent -> Nothing
|
|
|
|
; Given a button and an event, runs the program currently loaded in the editor.
|
|
|
|
(define (run-program button event)
|
|
|
|
; empty output text and set color to running
|
|
|
|
(send run-output set-value "")
|
|
|
|
(send run-output set-field-background run-col)
|
|
|
|
|
|
|
|
; run the program
|
2018-12-04 09:28:34 +00:00
|
|
|
(execute-content
|
|
|
|
(lambda (ps)
|
|
|
|
(define out (prog-state-output ps))
|
|
|
|
|
|
|
|
; set output and change color to ended
|
|
|
|
(send run-output set-value out)
|
|
|
|
(send run-output set-field-background end-col))))
|
2018-12-03 19:58:43 +00:00
|
|
|
|
|
|
|
; Definition of the run button widget
|
2018-12-02 17:05:50 +00:00
|
|
|
(define run-btn (new button% [parent f]
|
|
|
|
[label "Run"]
|
|
|
|
; Callback procedure for a button click:
|
2018-12-03 19:58:43 +00:00
|
|
|
[callback run-program]))
|
2018-12-01 21:06:12 +00:00
|
|
|
|
2018-12-03 19:58:43 +00:00
|
|
|
; Definition of the editor canves
|
2018-12-01 21:06:12 +00:00
|
|
|
(define c (new editor-canvas% [parent f]))
|
|
|
|
|
2018-12-03 19:58:43 +00:00
|
|
|
; Definition of editor text object.
|
|
|
|
(define text-pro% (text:line-numbers-mixin
|
|
|
|
(editor:standard-style-list-mixin
|
|
|
|
(color:text-mixin
|
|
|
|
(text:basic-mixin
|
|
|
|
(editor:basic-mixin text%))))))
|
|
|
|
(define editor (new text-pro%))
|
2018-12-02 17:05:50 +00:00
|
|
|
|
|
|
|
; Show line numbers in editor
|
2018-12-03 19:58:43 +00:00
|
|
|
(send editor show-line-numbers! #t)
|
|
|
|
|
|
|
|
; A BFToken is one of:
|
|
|
|
; - 'comment
|
|
|
|
; - 'instruction
|
|
|
|
; - 'shift
|
|
|
|
; - 'loop
|
|
|
|
; Interp: category of a bf program token
|
|
|
|
|
|
|
|
; A BFStyle is one of:
|
|
|
|
; - "Comment"
|
|
|
|
; - "Instruction"
|
|
|
|
; - "Shift"
|
|
|
|
; - "Loop"
|
|
|
|
; Interp: name of the style for a bf program token
|
|
|
|
|
|
|
|
; bf-token->bf-style: BFToken -> BFStyle
|
|
|
|
; Given a BFToken, returns the corresponding BFStyle.
|
|
|
|
(define (bf-token->bf-style token)
|
|
|
|
(cond [(symbol=? token 'comment) "Comment"]
|
|
|
|
[(symbol=? token 'loop) "Loop"]
|
|
|
|
[(symbol=? token 'shift) "Shift"]
|
|
|
|
[(symbol=? token 'instruction) "Instruction"]))
|
|
|
|
|
|
|
|
; bf-lexer: InputPort -> (values 1String BFToken #f Option<Nat> Option<Nat>)
|
|
|
|
; Given an input port, returns the BFToken of the instruction pointed by the
|
|
|
|
; port.
|
|
|
|
(define (bf-lexer port)
|
|
|
|
(define-values (_ __ pos) (port-next-location port))
|
|
|
|
(define c (read-char port))
|
|
|
|
(cond [(eof-object? c) (values c 'eof #f #f #f)]
|
|
|
|
[else
|
|
|
|
(define 1str (string c))
|
|
|
|
(define bf-token
|
|
|
|
(cond [(set-member? (set "+" "-" "," ".") 1str) 'instruction]
|
|
|
|
[(set-member? (set "<" ">") 1str) 'shift]
|
|
|
|
[(set-member? (set "[" "]") 1str) 'loop]
|
|
|
|
[else 'comment]))
|
|
|
|
(values 1str bf-token #f (+ pos) (+ pos 1))]))
|
|
|
|
|
2018-12-04 09:08:09 +00:00
|
|
|
; Syntax highlighting for brainf*ck
|
2018-12-03 19:58:43 +00:00
|
|
|
(send editor start-colorer bf-token->bf-style bf-lexer '())
|
|
|
|
|
|
|
|
; Define basic style for instructions (+ - , .)
|
|
|
|
(define delta (make-object style-delta%))
|
|
|
|
(send delta set-delta-foreground "blue")
|
|
|
|
(editor:set-standard-style-list-delta "Instruction" delta)
|
|
|
|
|
|
|
|
; Define style for shifting operations (< >)
|
|
|
|
(send delta set-delta-foreground "red")
|
|
|
|
(editor:set-standard-style-list-delta "Shift" delta)
|
|
|
|
|
|
|
|
; Define basic style for looping instructions ([ ])
|
|
|
|
(send delta set-delta-foreground "forestgreen")
|
|
|
|
(editor:set-standard-style-list-delta "Loop" delta)
|
2018-12-02 17:05:50 +00:00
|
|
|
|
2018-12-03 19:58:43 +00:00
|
|
|
; Define style of comments
|
|
|
|
(send delta set-delta-foreground "orange")
|
|
|
|
(editor:set-standard-style-list-delta "Comment" delta)
|
2018-12-02 17:05:50 +00:00
|
|
|
|
|
|
|
; Running output color
|
|
|
|
(define run-col (make-object color% 250 250 200))
|
|
|
|
|
|
|
|
; Output completed color
|
|
|
|
(define end-col (make-object color% 200 250 200))
|
2018-12-01 21:06:12 +00:00
|
|
|
|
|
|
|
(define mb (new menu-bar% [parent f]))
|
|
|
|
(define m-file (new menu% [label "File"] [parent mb]))
|
|
|
|
(define m-edit (new menu% [label "Edit"] [parent mb]))
|
|
|
|
|
2018-12-02 17:05:50 +00:00
|
|
|
; The run output text object
|
|
|
|
(define run-output (new text-field%
|
|
|
|
[style (list 'multiple 'vertical-label)]
|
|
|
|
[label "Execution output:"]
|
|
|
|
[parent f]))
|
2018-12-01 21:06:12 +00:00
|
|
|
|
|
|
|
(define mi-open
|
|
|
|
(new menu-item%
|
|
|
|
[label "Open"]
|
|
|
|
[parent m-file]
|
|
|
|
[callback
|
|
|
|
(lambda (i e)
|
|
|
|
(define path (get-file #f f))
|
|
|
|
(when path
|
2018-12-02 17:05:50 +00:00
|
|
|
(send editor load-file path 'text)))]
|
2018-12-01 21:06:12 +00:00
|
|
|
[shortcut #\o]
|
|
|
|
[shortcut-prefix '(ctl)]))
|
|
|
|
|
|
|
|
(define mi-save
|
|
|
|
(new menu-item%
|
|
|
|
[label "Save"]
|
|
|
|
[parent m-file]
|
|
|
|
[callback
|
|
|
|
(lambda (i e)
|
2018-12-02 17:05:50 +00:00
|
|
|
(send editor save-file #f 'text))]
|
2018-12-01 21:06:12 +00:00
|
|
|
[shortcut #\s]
|
|
|
|
[shortcut-prefix '(ctl)]))
|
|
|
|
|
|
|
|
(append-editor-operation-menu-items m-edit #f)
|
2018-12-02 17:05:50 +00:00
|
|
|
(send editor set-max-undo-history 100)
|
|
|
|
(send c set-editor editor)
|
2018-12-01 21:06:12 +00:00
|
|
|
(send f show #t)
|