Créer un compilateur/interpréteur Brainfuck

Tous langages

a marqué ce sujet comme résolu.

Un gros coup de déterrage ici, pour vous montrer la puissance de Kotlin !

Vous vous souvenez peut-être de ma version optimisée de l’interpéteur en Java. Voici une version plus rapide en Kotlin (10 secondes sur la fractale contre 12 avec Java sur mon PC actuel) et qui tient en moins de 100 lignes, imports et mise en forme correcte comprises :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package fr.spacefox.brainfuck

import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import kotlin.system.measureTimeMillis

class CompiledBrainFuck(strProgram: String) {

    private val instructions = strProgram
            .filter { it in listOf('+', '-', '>', '<', '[', ']', '.', ',') }
            .replace(">[-]<[->+<]", "m")    // Move
            .replace("[->+<]",      "a")    // Addition
            .replace("[-]",         "0")    // Cell reset
            .toCharArray()
    private val ram = IntArray(30000)
    private val inputReader = InputStreamReader(System.`in`)

    fun run() {
        val (compiled, parameters) = compile(instructions)
        var ramPtr = 0
        var programPtr = 0

        do {
            when (compiled[programPtr]) {
                '>', '<'    -> ramPtr += parameters[programPtr]
                '+', '-'    -> ram[ramPtr] = (ram[ramPtr] + parameters[programPtr]) % 0xFFFF
                '0'         -> ram[ramPtr] = 0
                'a'         -> { ram[ramPtr + 1] += ram[ramPtr] ; ram[ramPtr] = 0 }
                'm'         -> { ram[ramPtr + 1] = ram[ramPtr] ; ram[ramPtr] = 0 }
                '['         -> if (ram[ramPtr] == 0) programPtr = parameters[programPtr]
                ']'         -> if (ram[ramPtr] != 0) programPtr = parameters[programPtr]
                '.'         -> print(ram[ramPtr].toChar())
                ','         -> ram[ramPtr] = try { inputReader.read() } catch (e: IOException) { 0 }
            }
            programPtr++
        } while (programPtr < compiled.size)

    }
    private fun compile(unCompiled: CharArray): Pair<CharArray, IntArray> {

        val compiled = mutableListOf<Char>()
        val parameters = mutableListOf<Int>()
        var lastInstruction = '\u0000'

        for (instruction in unCompiled) {
            when (instruction) {
                '>', '+' -> if (instruction == lastInstruction) {
                                parameters[parameters.lastIndex]++
                            } else {
                                compiled.add(instruction)
                                parameters.add(1)
                            }
                '<', '-' -> if (instruction == lastInstruction) {
                                parameters[parameters.lastIndex]--
                            } else {
                                compiled.add(instruction)
                                parameters.add(-1)
                            }
                else -> {
                    compiled.add(instruction)
                    parameters.add(0)
                }
            }
            lastInstruction = instruction
        }

        for (open in 0..compiled.lastIndex) {
            if (compiled[open] == '[') {
                var loops = 1
                var close = open
                while (loops > 0) {
                    close++
                    when {
                        compiled[close] == '[' -> loops++
                        compiled[close] == ']' -> loops--
                    }
                }
                parameters[open] = close    // Match [ → ]
                parameters[close] = open    // Match ] → [
            }
        }

        return Pair(compiled.toCharArray(), parameters.toIntArray())
    }
}

fun main(args: Array<String>) {
    val time = measureTimeMillis { CompiledBrainFuck(File(args[0]).readText()).run() }
    println("Completed in $time ms")
}

Édité par SpaceFox

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte