Compiler/virtual machine interpreter: Difference between revisions

New post.
(New post.)
 
(10 intermediate revisions by 5 users not shown)
Line 153:
; A simple example virtual machine:
 
<langsyntaxhighlight lang="python">def run_vm(data_size)
int stack[data_size + 1000]
set stack[0..data_size - 1] to 0
Line 190:
elif op == PRTS: print the constant string referred to by stack[-1]; stack.pop()
elif op == PRTI: print stack[-1] as an integer; stack.pop()
elif op == HALT: break</langsyntaxhighlight>
 
; Additional examples
Line 219:
 
 
<syntaxhighlight lang="ada">--
<lang Ada>--
-- The Rosetta Code Virtual Machine, in Ada.
--
Line 1,153:
 
Set_Exit_Status (status);
end VM;</langsyntaxhighlight>
 
 
Line 1,169:
 
=={{header|Aime}}==
<syntaxhighlight lang="text">integer n, pc, sp;
file f;
text s;
Line 1,255:
isk_greater(code, pc, pc);
}
}</langsyntaxhighlight>
 
=={{header|ALGOL W}}==
<langsyntaxhighlight lang="algolw">begin % virtual machine interpreter %
% string literals %
string(256) array stringValue ( 0 :: 256 );
Line 1,564:
end while_not_halted
end
end.</langsyntaxhighlight>
 
=={{header|ATS}}==
 
===Interpreter===
 
{{works with|ATS|Postiats 0.4.1}}
 
Line 1,575 ⟶ 1,578:
(Without the C optimizer, ATS code can run much, much more slowly. It is worth comparing the Mandelbrot example with and without the optimizer.)
 
<langsyntaxhighlight lang="ats">(*
Usage: vm [INPUTFILE [OUTPUTFILE]]
If INPUTFILE or OUTPUTFILE is "-" or missing, then standard input
Line 3,377 ⟶ 3,380:
}
 
(********************************************************************)</langsyntaxhighlight>
 
{{out}}
Line 3,390 ⟶ 3,393:
count is: 8
count is: 9</pre>
 
===Compiler===
 
It seemed interesting to write translators from virtual machine code to other languages. Find at https://pastebin.com/pntTVTN3 a translator from Rosetta Code VM assembly language to ATS. The ATS program can be compiled to native code, which should run pretty fast if you use the C optimizer.
 
An ongoing project, to extend the translator to output languages other than ATS, is at https://sourceforge.net/p/chemoelectric/rosettacode-contributions/ci/default/tree/vmc.dats
 
=={{header|AWK}}==
Tested with gawk 4.1.1 and mawk 1.3.4.
<syntaxhighlight lang="awk">
<lang AWK>
function error(msg) {
printf("%s\n", msg)
Line 3,548 ⟶ 3,557:
run_vm(data_size)
}
</syntaxhighlight>
</lang>
{{out|case=count}}
<b>
Line 3,566 ⟶ 3,575:
=={{header|C}}==
Tested with gcc 4.81 and later, compiles warning free with -Wall -Wextra
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
Line 3,832 ⟶ 3,841:
int data[1000 + data_size];
run_vm(object, data, data_size, string_pool);
}</langsyntaxhighlight>
 
=={{header|C++}}==
This examples passes all tests, although for brevity of output only one test result is shown.
<syntaxhighlight lang="c++">
#include <cstdint>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
 
std::vector<std::string> split_string(const std::string& text, const char& delimiter) {
std::vector<std::string> lines;
std::istringstream stream(text);
std::string line;
while ( std::getline(stream, line, delimiter) ) {
if ( ! line.empty() ) {
lines.emplace_back(line);
}
}
return lines;
}
 
std::string parseString(const std::string& text) {
std::string result = "";
uint32_t i = 0;
while ( i < text.length() ) {
if ( text[i] == '\\' && i + 1 < text.length() ) {
if ( text[i + 1] == 'n' ) {
result += "\n";
i++;
} else if ( text[i + 1] == '\\') {
result += "\\";
i++;
}
} else {
result += text[i];
}
i++;
}
 
return result;
}
 
void add_to_codes(const uint32_t& number, std::vector<uint8_t>& codes) {
for ( uint32_t i = 0; i < 32; i += 8 ) {
codes.emplace_back((number >> i) & 0xff);
}
}
 
uint32_t operand(const uint32_t& index, const std::vector<uint8_t>& codes) {
uint32_t result = 0;
for ( uint32_t i = index + 3; i >= index; --i ) {
result = ( result << 8 ) + codes[i];
}
 
return result;
}
 
struct VirtualMachineInfo {
uint32_t data_size;
std::vector<std::string> vm_strings;
std::vector<uint8_t> codes;
};
 
enum class Op_code {
HALT, ADD, SUB, MUL, DIV, MOD, LT, GT, LE, GE, EQ, NE, AND, OR, NEG, NOT,
PRTC, PRTI, PRTS, FETCH, STORE, PUSH, JMP, JZ
};
 
std::unordered_map<std::string, Op_code> string_to_enum = {
{ "halt", Op_code::HALT }, { "add", Op_code::ADD }, { "sub", Op_code::SUB },
{ "mul", Op_code::MUL }, { "div", Op_code::DIV }, { "mod", Op_code::MOD },
{ "lt", Op_code::LT }, { "gt", Op_code::GT }, { "le", Op_code::LE },
{ "ge", Op_code::GE }, { "eq", Op_code::EQ }, { "ne", Op_code::NE },
{ "and", Op_code::AND }, { "or", Op_code::OR }, { "neg", Op_code::NEG },
{ "not", Op_code::NOT }, { "prtc", Op_code::PRTC }, { "prti", Op_code::PRTI },
{ "prts", Op_code::PRTS }, { "fetch", Op_code::FETCH }, { "store", Op_code::STORE },
{ "push", Op_code::PUSH }, { "jmp", Op_code::JMP }, { "jz", Op_code::JZ }
};
 
VirtualMachineInfo load_code(const std::string& file_path) {
std::ifstream stream(file_path);
std::vector<std::string> lines;
std::string line;
 
while ( std::getline(stream, line) ) {
lines.emplace_back(line);
}
 
line = lines.front();
if ( line.substr(0, 3) == "lex" ) {
lines.erase(lines.begin());
line = lines.front();
}
 
std::vector<std::string> sections = split_string(line, ' ');
const uint32_t data_size = std::stoi(sections[1]);
const uint32_t string_count = std::stoi(sections[3]);
 
std::vector<std::string> vm_strings = { };
for ( uint32_t i = 1; i <= string_count; ++i ) {
std::string content = lines[i].substr(1, lines[i].length() - 2);
vm_strings.emplace_back(parseString(content));
}
 
uint32_t offset = 0;
std::vector<uint8_t> codes = { };
for ( uint32_t i = string_count + 1; i < lines.size(); ++i ) {
sections = split_string(lines[i], ' ');
offset = std::stoi(sections[0]);
Op_code op_code = string_to_enum[sections[1]];
codes.emplace_back(static_cast<uint8_t>(op_code));
 
switch ( op_code ) {
case Op_code::FETCH :
case Op_code::STORE :
add_to_codes(std::stoi(sections[2]
.substr(1, sections[2].length() - 2)), codes); break;
case Op_code::PUSH : add_to_codes(std::stoi(sections[2]), codes); break;
case Op_code::JMP :
case Op_code::JZ : add_to_codes(std::stoi(sections[3]) - offset - 1, codes); break;
default : break;
}
}
 
return VirtualMachineInfo(data_size, vm_strings, codes);
}
 
void runVirtualMachine(
const uint32_t& data_size, const std::vector<std::string>& vm_strings, const std::vector<uint8_t>& codes) {
const uint32_t word_size = 4;
std::vector<int32_t> stack(data_size, 0);
uint32_t index = 0;
Op_code op_code;
 
while ( op_code != Op_code::HALT ) {
op_code = static_cast<Op_code>(codes[index]);
index++;
 
switch ( op_code ) {
case Op_code::HALT : break;
case Op_code::ADD : stack[stack.size() - 2] += stack.back(); stack.pop_back(); break;
case Op_code::SUB : stack[stack.size() - 2] -= stack.back(); stack.pop_back(); break;
case Op_code::MUL : stack[stack.size() - 2] *= stack.back(); stack.pop_back(); break;
case Op_code::DIV : stack[stack.size() - 2] /= stack.back(); stack.pop_back(); break;
case Op_code::MOD : stack[stack.size() - 2] %= stack.back(); stack.pop_back(); break;
case Op_code::LT : { stack[stack.size() - 2] = ( stack[stack.size() - 2] < stack.back() ) ? 1 : 0;
stack.pop_back(); break;
}
case Op_code::GT : { stack[stack.size() - 2] = ( stack[stack.size() - 2] > stack.back() ) ? 1 : 0;
stack.pop_back(); break;
}
case Op_code::LE : { stack[stack.size() - 2] = ( stack[stack.size() - 2] <= stack.back() ) ? 1 : 0;
stack.pop_back(); break;
}
case Op_code::GE : { stack[stack.size() - 2] = ( stack[stack.size() - 2] >= stack.back() ) ? 1 : 0;
stack.pop_back(); break;
}
case Op_code::EQ : { stack[stack.size() - 2] = ( stack[stack.size() - 2] == stack.back() ) ? 1 : 0;
stack.pop_back(); break;
}
case Op_code::NE : { stack[stack.size() - 2] = ( stack[stack.size() - 2] != stack.back() ) ? 1 : 0;
stack.pop_back(); break;
}
case Op_code::AND : { uint32_t value = ( stack[stack.size() - 2] != 0 && stack.back() != 0 ) ? 1 : 0;
stack[stack.size() - 2] = value; stack.pop_back(); break;
}
case Op_code::OR : { uint32_t value = ( stack[stack.size() - 2] != 0 || stack.back() != 0 ) ? 1 : 0;
stack[stack.size() - 2] = value; stack.pop_back(); break;
}
case Op_code::NEG : stack.back() = -stack.back(); break;
case Op_code::NOT : stack.back() = ( stack.back() == 0 ) ? 1 : 0; break;
case Op_code::PRTC : std::cout << static_cast<char>(stack.back()); stack.pop_back(); break;
case Op_code::PRTI : std::cout << stack.back(); stack.pop_back(); break;
case Op_code::PRTS : std::cout << vm_strings[stack.back()]; stack.pop_back(); break;
case Op_code::FETCH : stack.emplace_back(stack[operand(index, codes)]); index += word_size; break;
case Op_code::STORE : { stack[operand(index, codes)] = stack.back(); index += word_size;
stack.pop_back(); break;
}
case Op_code::PUSH : stack.emplace_back(operand(index, codes)); index += word_size; break;
case Op_code::JMP : index += operand(index, codes); break;
case Op_code::JZ : { index += ( stack.back() == 0 ) ? operand(index, codes) : word_size;
stack.pop_back(); break;
}
}
}
}
 
int main() {
VirtualMachineInfo info = load_code("Compiler Test Cases/AsciiMandlebrot.txt");
runVirtualMachine(info.data_size, info.vm_strings, info.codes);
}
</syntaxhighlight>
{{ out }}
<pre>
1111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222211111
1111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222211
1111111111111111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333222222222222222222222222222222222222222
1111111111111222222222233333333333333333333333344444456655544443333332222222222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333333222222222222222222222222222222
11111111111222222333333333333333333333334444444445555679@@@@7654444443333333222222222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98755544444433333332222222222222222222222222
1111111122223333333333333333333333344444444445556668@@@ @@@76555544444333333322222222222222222222222
1111111222233333333333333333333344444444455566667778@@ @987666555544433333333222222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@877779@5443333333322222222222222222222
1111112233333333333333333334444455555556679@ @@@ @@@@@@ 8544333333333222222222222222222
1111122333333333333333334445555555556666789@@@ @86554433333333322222222222222222
1111123333333333333444456666555556666778@@ @ @@87655443333333332222222222222222
111123333333344444455568@887789@8777788@@@ @@@@65444333333332222222222222222
111133334444444455555668@@@@@@@@@@@@99@@@ @@765444333333333222222222222222
111133444444445555556778@@@ @@@@ @855444333333333222222222222222
11124444444455555668@99@@ @ @655444433333333322222222222222
11134555556666677789@@ @86655444433333333322222222222222
111 @@876555444433333333322222222222222
11134555556666677789@@ @86655444433333333322222222222222
11124444444455555668@99@@ @ @655444433333333322222222222222
111133444444445555556778@@@ @@@@ @855444333333333222222222222222
111133334444444455555668@@@@@@@@@@@@99@@@ @@765444333333333222222222222222
111123333333344444455568@887789@8777788@@@ @@@@65444333333332222222222222222
1111123333333333333444456666555556666778@@ @ @@87655443333333332222222222222222
1111122333333333333333334445555555556666789@@@ @86554433333333322222222222222222
1111112233333333333333333334444455555556679@ @@@ @@@@@@ 8544333333333222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@877779@5443333333322222222222222222222
1111111222233333333333333333333344444444455566667778@@ @987666555544433333333222222222222222222222
1111111122223333333333333333333333344444444445556668@@@ @@@76555544444333333322222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98755544444433333332222222222222222222222222
11111111111222222333333333333333333333334444444445555679@@@@7654444443333333222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333333222222222222222222222222222222
1111111111111222222222233333333333333333333333344444456655544443333332222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333222222222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222222222222222222222222222222222222
1111111111111111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222
1111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222211
</pre>
 
=={{header|COBOL}}==
Code by Steve Williams (with changes to work around code highlighting issues). Tested with GnuCOBOL 2.2.
 
<langsyntaxhighlight lang="cobol"> >>SOURCE FORMAT IS FREE
identification division.
*> this code is dedicated to the public domain
Line 4,258 ⟶ 4,505:
end program emitword.
 
end program vminterpreter.</langsyntaxhighlight>
 
{{out|case=Count}}
Line 4,282 ⟶ 4,529:
 
 
<langsyntaxhighlight lang="lisp">#!/bin/sh
#|-*- mode:lisp -*-|#
#|
Line 5,006 ⟶ 5,253:
(uiop:quit 0)))
 
;;; vim: set ft=lisp lisp:</langsyntaxhighlight>
 
 
Line 5,032 ⟶ 5,279:
 
 
<syntaxhighlight lang="d">//
<lang D>//
// The Rosetta Code Virtual Machine in D.
//
Line 5,938 ⟶ 6,185:
 
return 0;
}</langsyntaxhighlight>
 
 
Line 5,957 ⟶ 6,204:
=={{header|Forth}}==
Tested with Gforth 0.7.3
<langsyntaxhighlight Forthlang="forth">CREATE BUF 0 , \ single-character look-ahead buffer
: PEEK BUF @ 0= IF KEY BUF ! THEN BUF @ ;
: GETC PEEK 0 BUF ! ;
Line 6,039 ⟶ 6,286:
: RUN BYTECODE @ A !
BEGIN C@A+ CELLS OPS + @ EXECUTE AGAIN ;
>HEADER >BYTECODE RUN</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|gfortran|11.2.1}}
Fortran 2008/2018 code with some limited use of the C preprocessor. If you are on a platform with case-sensitive filenames, and call the source file vm.F90, then gfortran will know to use the C preprocessor.
<langsyntaxhighlight lang="fortran">module compiler_type_kinds
use, intrinsic :: iso_fortran_env, only: int32
use, intrinsic :: iso_fortran_env, only: int64
Line 7,577 ⟶ 7,824:
end subroutine print_usage
end program vm</langsyntaxhighlight>
 
{{out}}
Line 7,593 ⟶ 7,840:
=={{header|Go}}==
{{trans|Python}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 7,895 ⟶ 8,142:
scanner = bufio.NewScanner(codeGen)
runVM(loadCode())
}</langsyntaxhighlight>
 
{{out}}
Line 7,913 ⟶ 8,160:
=={{header|Icon}}==
{{trans|ObjectIcon}}
<langsyntaxhighlight lang="icon"># -*- Icon -*-
#
# The Rosetta Code virtual machine in Icon. Migrated from the
Line 8,287 ⟶ 8,534:
write(&errout, "Bad opcode.")
exit(1)
end</langsyntaxhighlight>
 
{{out}}
Line 8,303 ⟶ 8,550:
=={{header|J}}==
Implementation:
<langsyntaxhighlight Jlang="j">(opcodes)=: opcodes=: ;:{{)n
fetch store push add sub mul div mod lt gt le ge
eq ne and or neg not jmp jz prtc prts prti halt
Line 8,378 ⟶ 8,625:
pc=: pc+k
end.
}}</langsyntaxhighlight>
 
Task example:
<langsyntaxhighlight Jlang="j">count=:{{)n
count = 1;
while (count < 10) {
Line 8,399 ⟶ 8,646:
count is: 8
count is: 9
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
This examples passes all tests, although for brevity of output only one test result is shown.
<syntaxhighlight lang="java">
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
 
public final class CompilerVirtualMachineInterpreter {
 
public static void main(String[] args) throws IOException {
Path filePath = Path.of("Compiler Test Cases/AsciiMandlebrot.txt");
VirtualMachineInfo info = loadCode(filePath);
runVirtualMachine(info.dataSize, info.vmStrings, info.codes());
}
 
private static void runVirtualMachine(int dataSize, List<String> vmStrings, List<Byte> codes) {
final int wordSize = 4;
Stack<Integer> stack = new Stack<Integer>();
for ( int i = 0; i < dataSize; i++ ) {
stack.push(0);
}
int index = 0;
OpCode opCode = null;
while ( opCode != OpCode.HALT ) {
opCode = OpCode.havingCode(codes.get(index));
index += 1;
switch ( opCode ) {
case HALT -> { }
case ADD -> stack.set(stack.size() - 2, stack.get(stack.size() - 2) + stack.pop());
case SUB -> stack.set(stack.size() - 2, stack.get(stack.size() - 2) - stack.pop());
case MUL -> stack.set(stack.size() - 2, stack.get(stack.size() - 2) * stack.pop());
case DIV -> stack.set(stack.size() - 2, stack.get(stack.size() - 2) / stack.pop());
case MOD -> stack.set(stack.size() - 2, Math.floorMod(stack.get(stack.size() - 2), stack.pop()));
case LT -> stack.set(stack.size() - 2, ( stack.get(stack.size() - 2) < stack.pop() ) ? 1 : 0);
case GT -> stack.set(stack.size() - 2, ( stack.get(stack.size() - 2) > stack.pop() ) ? 1 : 0);
case LE -> stack.set(stack.size() - 2, ( stack.get(stack.size() - 2) <= stack.pop() ) ? 1 : 0);
case GE -> stack.set(stack.size() - 2, ( stack.get(stack.size() - 2) >= stack.pop() ) ? 1 : 0);
case EQ -> stack.set(stack.size() - 2, ( stack.get(stack.size() - 2) == stack.pop() ) ? 1 : 0);
case NE -> stack.set(stack.size() - 2, ( stack.get(stack.size() - 2) != stack.pop() ) ? 1 : 0);
case AND -> { final int value = ( stack.get(stack.size() - 2) != 0 && stack.pop() != 0 ) ? 1 : 0;
stack.set(stack.size() - 1, value);
}
case OR -> { final int value = ( stack.get(stack.size() - 2) != 0 || stack.pop() != 0 ) ? 1 : 0;
stack.set(stack.size() - 1, value);
}
case NEG -> stack.set(stack.size() - 1, -stack.peek());
case NOT -> stack.set(stack.size() - 1, ( stack.peek() == 0 ) ? 1 : 0);
case PRTC -> System.out.print((char) stack.pop().intValue());
case PRTI -> System.out.print(stack.pop());
case PRTS -> System.out.print(vmStrings.get(stack.pop()));
case FETCH -> { stack.push(stack.get(operand(index, codes))); index += wordSize; }
case STORE -> { stack.set(operand(index, codes), stack.pop()); index += wordSize; }
case PUSH -> { stack.push(operand(index, codes)); index += wordSize; }
case JMP -> index += operand(index, codes);
case JZ -> index += ( stack.pop() == 0 ) ? operand(index, codes) : wordSize;
}
}
}
private static VirtualMachineInfo loadCode(Path filePath) throws IOException {
List<String> lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
String line = lines.getFirst();
if ( line.startsWith("lex") ) {
lines.removeFirst();
line = lines.getFirst();
}
String[] sections = line.trim().split(" ");
final int dataSize = Integer.parseInt(sections[1]);
final int stringCount = Integer.parseInt(sections[3]);
List<String> VMstrings = new ArrayList<String>();
for ( int i = 1; i <= stringCount; i++ ) {
String content = lines.get(i).substring(1, lines.get(i).length() - 1);
VMstrings.addLast(parseString(content));
}
int offset = 0;
List<Byte> codes = new ArrayList<Byte>();
for ( int i = stringCount + 1; i < lines.size(); i++ ) {
sections = lines.get(i).trim().split("\\s+");
offset = Integer.parseInt(sections[0]);
OpCode opCode = OpCode.valueOf(sections[1].toUpperCase());
codes.addLast(opCode.byteCode());
switch ( opCode ) {
case FETCH, STORE -> addToCodes(Integer.parseInt(sections[2]
.substring(1, sections[2].length() - 1)), codes);
case PUSH -> addToCodes(Integer.parseInt(sections[2]), codes);
case JMP, JZ -> addToCodes(Integer.parseInt(sections[3]) - offset - 1, codes);
default -> { }
}
}
return new VirtualMachineInfo(dataSize, VMstrings, codes);
}
private static int operand(int index, List<Byte> codes) {
byteBuffer.clear();
for ( int i = index; i < index + 4; i++ ) {
byteBuffer.put(codes.get(i));
}
byteBuffer.flip();
return byteBuffer.getInt();
}
private static void addToCodes(int number, List<Byte> codes) {
byteBuffer.clear();
byteBuffer.putInt(number);
byteBuffer.flip();
for ( byte bb : byteBuffer.array() ) {
codes.addLast(bb);
}
}
private static String parseString(String text) {
StringBuilder result = new StringBuilder();
int i = 0;
while ( i < text.length() ) {
if ( text.charAt(i) == '\\' && i + 1 < text.length() ) {
if ( text.charAt(i + 1) == 'n' ) {
result.append("\n");
i += 1;
} else if ( text.charAt(i + 1) == '\\') {
result.append("\\");
i += 1;
}
} else {
result.append(text.charAt(i));
}
i += 1;
}
return result.toString();
}
private static ByteBuffer byteBuffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
private static enum OpCode {
HALT(0), ADD(1), SUB(2), MUL(3), DIV(4), MOD(5), LT(6), GT(7), LE(8), GE(9), EQ(10), NE(11),
AND(12), OR(13), NEG(14), NOT(15),
PRTC(16), PRTI(17), PRTS(18), FETCH(19), STORE(20), PUSH(21), JMP(22), JZ(23);
public byte byteCode() {
return (byte) byteCode;
}
public static OpCode havingCode(Byte byteCode) {
return op_codes[(int) byteCode];
}
private OpCode(int aByteCode) {
byteCode = aByteCode;
}
private int byteCode;
private static OpCode[] op_codes = values();
}
private static record VirtualMachineInfo(int dataSize, List<String> vmStrings, List<Byte> codes) {}
 
}
</syntaxhighlight>
{{ out }}
<pre>
1111111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222211111
1111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222211
1111111111111111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333222222222222222222222222222222222222222
1111111111111222222222233333333333333333333333344444456655544443333332222222222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333333222222222222222222222222222222
11111111111222222333333333333333333333334444444445555679@@@@7654444443333333222222222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98755544444433333332222222222222222222222222
1111111122223333333333333333333333344444444445556668@@@ @@@76555544444333333322222222222222222222222
1111111222233333333333333333333344444444455566667778@@ @987666555544433333333222222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@877779@5443333333322222222222222222222
1111112233333333333333333334444455555556679@ @@@ @@@@@@ 8544333333333222222222222222222
1111122333333333333333334445555555556666789@@@ @86554433333333322222222222222222
1111123333333333333444456666555556666778@@ @ @@87655443333333332222222222222222
111123333333344444455568@887789@8777788@@@ @@@@65444333333332222222222222222
111133334444444455555668@@@@@@@@@@@@99@@@ @@765444333333333222222222222222
111133444444445555556778@@@ @@@@ @855444333333333222222222222222
11124444444455555668@99@@ @ @655444433333333322222222222222
11134555556666677789@@ @86655444433333333322222222222222
111 @@876555444433333333322222222222222
11134555556666677789@@ @86655444433333333322222222222222
11124444444455555668@99@@ @ @655444433333333322222222222222
111133444444445555556778@@@ @@@@ @855444333333333222222222222222
111133334444444455555668@@@@@@@@@@@@99@@@ @@765444333333333222222222222222
111123333333344444455568@887789@8777788@@@ @@@@65444333333332222222222222222
1111123333333333333444456666555556666778@@ @ @@87655443333333332222222222222222
1111122333333333333333334445555555556666789@@@ @86554433333333322222222222222222
1111112233333333333333333334444455555556679@ @@@ @@@@@@ 8544333333333222222222222222222
111111122333333333333333333333444444455556@@@@@99@@@@@@ @@@@@@877779@5443333333322222222222222222222
1111111222233333333333333333333344444444455566667778@@ @987666555544433333333222222222222222222222
1111111122223333333333333333333333344444444445556668@@@ @@@76555544444333333322222222222222222222222
1111111112222223333333333333333333333444444444455556789@@@@98755544444433333332222222222222222222222222
11111111111222222333333333333333333333334444444445555679@@@@7654444443333333222222222222222222222222222
1111111111112222222233333333333333333333333444444445567@@6665444444333333222222222222222222222222222222
1111111111111222222222233333333333333333333333344444456655544443333332222222222222222222222222222222222
1111111111111112222222222222333333333333333333333333333333333333222222222222222222222222222222222222222
1111111111111111222222222222222222233333333333333333333333222222222222222222222222222222222222222222222
1111111111111111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222
1111111111111111111122222222222222222222222222222222222222222222222222222222222222222222222222222222211
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">mutable struct VM32
code::Vector{UInt8}
stack::Vector{Int32}
Line 8,505 ⟶ 8,973:
const vm = assemble(iob)
runvm(vm)
</langsyntaxhighlight>{{output}}<pre>
count is: 1
count is: 2
Line 8,519 ⟶ 8,987:
=={{header|M2000 Interpreter}}==
===Using Select Case===
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Virtual_Machine_Interpreter (a$){
\\ function to extract string, replacing escape codes.
Line 8,692 ⟶ 9,160:
65 halt
}
</syntaxhighlight>
</lang>
 
===Using Lambda functions===
Line 8,698 ⟶ 9,166:
A call local to function pass the current scope to function, so it's like a call to subroutine, but faster.
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Virtual_Machine_Interpreter (a$){
\\ function to extract string, replacing escape codes.
Line 8,847 ⟶ 9,315:
65 halt
}
</syntaxhighlight>
</lang>
 
=={{header|Mercury}}==
Line 8,860 ⟶ 9,328:
 
 
<langsyntaxhighlight Mercurylang="mercury">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% The Rosetta Code Virtual Machine, in Mercury.
Line 9,751 ⟶ 10,219:
%%% prolog-indent-width: 2
%%% end:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</langsyntaxhighlight>
 
 
Line 9,773 ⟶ 10,241:
=={{header|Nim}}==
 
<langsyntaxhighlight Nimlang="nim">import os, parseutils, strutils, strscans, strformat
 
type
Line 10,093 ⟶ 10,561:
 
vm.load(code)
vm.run()</langsyntaxhighlight>
 
All tests passed.
 
=={{header|ObjectIcon}}==
<langsyntaxhighlight lang="objecticon"># -*- ObjectIcon -*-
#
# The Rosetta Code virtual machine in Object Icon.
Line 10,505 ⟶ 10,973:
exit(1)
end
end</langsyntaxhighlight>
 
{{out}}
Line 10,521 ⟶ 10,989:
=={{header|Perl}}==
Tested with perl v5.26.1
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl
 
# http://www.rosettacode.org/wiki/Compiler/virtual_machine_interpreter
Line 10,570 ⟶ 11,038:
}
 
$ops[vec($binary, $pc++, 8)][1]->() while 1; # run it</langsyntaxhighlight>
Passes all tests.
 
=={{header|Phix}}==
Reusing cgen.e from the [[Compiler/code_generator#Phix|Code Generator task]]
<!--<langsyntaxhighlight Phixlang="phix">(notonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Compiler\vm.exw
Line 10,615 ⟶ 11,083:
<span style="color: #000080;font-style:italic;">--main(command_line())</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"count.c"</span><span style="color: #0000FF;">})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 10,633 ⟶ 11,101:
 
 
<langsyntaxhighlight lang="prolog">%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% The Rosetta Code Virtual Machine, for GNU Prolog.
Line 10,999 ⟶ 11,467:
%%% prolog-indent-width: 2
%%% end:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</langsyntaxhighlight>
 
 
Line 11,016 ⟶ 11,484:
=={{header|Python}}==
Tested with Python 2.7 and 3.x
<langsyntaxhighlight Pythonlang="python">from __future__ import print_function
import sys, struct
 
Line 11,183 ⟶ 11,651:
 
data_size = load_code()
run_vm(data_size)</langsyntaxhighlight>
 
=={{header|Racket}}==
Line 11,194 ⟶ 11,662:
 
 
<langsyntaxhighlight Racketlang="racket">#lang typed/racket
;;;
;;; The Rosetta Code Virtual Machine, in Typed Racket.
Line 11,941 ⟶ 12,409:
(close-output-port outf))
 
(exit 0)))))</langsyntaxhighlight>
 
 
Line 11,966 ⟶ 12,434:
 
{{trans|Perl}}
<syntaxhighlight lang="raku" perl6line>my @CODE = q:to/END/.lines;
Datasize: 3 Strings: 2
"count is: "
Line 12,043 ⟶ 12,511:
$pc += $w;
%ops{%n2op{ $opcode }}();
}</langsyntaxhighlight>
{{out}}
<pre>count is: 1
Line 12,057 ⟶ 12,525:
=={{header|RATFOR}}==
{{works with|ratfor77|[https://sourceforge.net/p/chemoelectric/ratfor77/ public domain 1.0]}}
{{works with|gfortran|11.23.10}}
{{works with|f2c|20100827}}
 
 
<langsyntaxhighlight lang="ratfor">######################################################################
#
# The Rosetta Code code virtual machine in Ratfor 77.
Line 13,293 ⟶ 13,761:
end
 
######################################################################</langsyntaxhighlight>
 
 
 
 
{{out}}
<pre>$ ratfor77 vm-in-ratfor.r > vm-in-ratfor.f && gfortran -O2 -fcheck=all -std=legacy vm-in-ratfor.f && ./a.out < compiler-tests/primes.vm
3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime
23 is prime
29 is prime
31 is prime
37 is prime
41 is prime
43 is prime
47 is prime
53 is prime
59 is prime
61 is prime
67 is prime
71 is prime
73 is prime
79 is prime
83 is prime
89 is prime
97 is prime
101 is prime
Total primes found: 26</pre>
 
=={{header|Scala}}==
Line 13,304 ⟶ 13,798:
The following code implements a virtual machine for the output of the [http://rosettacode.org/wiki/Compiler/code_generator#Scala code generator].
 
<langsyntaxhighlight lang="scala">
package xyz.hyperreal.rosettacodeCompiler
 
Line 13,521 ⟶ 14,015:
 
}
</syntaxhighlight>
</lang>
 
The above code depends on the function <tt>unescape()</tt> to perform string escape sequence translation. That function is defined in the following separate source file.
 
<langsyntaxhighlight lang="scala">
package xyz.hyperreal
 
Line 13,553 ⟶ 14,047:
 
}
</syntaxhighlight>
</lang>
 
=={{header|Scheme}}==
Line 13,561 ⟶ 14,055:
All of the "Compiler/Sample programs" are correctly interpreted.
 
<langsyntaxhighlight lang="scheme">
(import (scheme base)
(scheme char)
Line 13,724 ⟶ 14,218:
(run-program data strings code))
(display "Error: pass a .asm filename\n"))
</syntaxhighlight>
</lang>
 
=={{header|Wren}}==
Line 13,732 ⟶ 14,226:
{{libheader|Wren-fmt}}
{{libheader|Wren-ioutil}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Enum
import "./crypto" for Bytes
import "./fmt" for Conv
import "./ioutil" for FileUtil
 
var codes = [
Line 13,998 ⟶ 14,492:
lines = FileUtil.readLines("codegen.txt")
lineCount = lines.count
runVM.call(loadCode.call())</langsyntaxhighlight>
 
{{out}}
Line 14,014 ⟶ 14,508:
 
=={{header|Zig}}==
<langsyntaxhighlight lang="zig">
const std = @import("std");
 
Line 14,337 ⟶ 14,831:
}
}
</syntaxhighlight>
</lang>
 
=={{header|zkl}}==
{{trans|Python}}
File rvm.zkl:
<langsyntaxhighlight lang="zkl">// This is a little endian machine
const WORD_SIZE=4;
const{ var _n=-1; var[proxy]N=fcn{ _n+=1 } } // enumerator
Line 14,403 ⟶ 14,897:
code.del(0,sz+2);
}
run_vm(code,1000);</langsyntaxhighlight>
The binary code file code.bin:
{{out}}
871

edits