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:
<
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</
; Additional examples
Line 219:
<syntaxhighlight lang="ada">--
-- The Rosetta Code Virtual Machine, in Ada.
--
Line 1,153:
Set_Exit_Status (status);
end VM;</
Line 1,169:
=={{header|Aime}}==
<syntaxhighlight lang="text">integer n, pc, sp;
file f;
text s;
Line 1,255:
isk_greater(code, pc, pc);
}
}</
=={{header|ALGOL W}}==
<
% string literals %
string(256) array stringValue ( 0 :: 256 );
Line 1,564:
end while_not_halted
end
end.</
=={{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.)
<
Usage: vm [INPUTFILE [OUTPUTFILE]]
If INPUTFILE or OUTPUTFILE is "-" or missing, then standard input
Line 3,377 ⟶ 3,380:
}
(********************************************************************)</
{{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">
function error(msg) {
printf("%s\n", msg)
Line 3,548 ⟶ 3,557:
run_vm(data_size)
}
</syntaxhighlight>
{{out|case=count}}
<b>
Line 3,566 ⟶ 3,575:
=={{header|C}}==
Tested with gcc 4.81 and later, compiles warning free with -Wall -Wextra
<
#include <stdlib.h>
#include <stdarg.h>
Line 3,832 ⟶ 3,841:
int data[1000 + data_size];
run_vm(object, data, data_size, string_pool);
}</
=={{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.
<
identification division.
*> this code is dedicated to the public domain
Line 4,258 ⟶ 4,505:
end program emitword.
end program vminterpreter.</
{{out|case=Count}}
Line 4,282 ⟶ 4,529:
<
#|-*- mode:lisp -*-|#
#|
Line 5,006 ⟶ 5,253:
(uiop:quit 0)))
;;; vim: set ft=lisp lisp:</
Line 5,032 ⟶ 5,279:
<syntaxhighlight lang="d">//
// The Rosetta Code Virtual Machine in D.
//
Line 5,938 ⟶ 6,185:
return 0;
}</
Line 5,957 ⟶ 6,204:
=={{header|Forth}}==
Tested with Gforth 0.7.3
<
: 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</
=={{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.
<
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</
{{out}}
Line 7,593 ⟶ 7,840:
=={{header|Go}}==
{{trans|Python}}
<
import (
Line 7,895 ⟶ 8,142:
scanner = bufio.NewScanner(codeGen)
runVM(loadCode())
}</
{{out}}
Line 7,913 ⟶ 8,160:
=={{header|Icon}}==
{{trans|ObjectIcon}}
<
#
# The Rosetta Code virtual machine in Icon. Migrated from the
Line 8,287 ⟶ 8,534:
write(&errout, "Bad opcode.")
exit(1)
end</
{{out}}
Line 8,303 ⟶ 8,550:
=={{header|J}}==
Implementation:
<
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.
}}</
Task example:
<
count = 1;
while (count < 10) {
Line 8,399 ⟶ 8,646:
count is: 8
count is: 9
</syntaxhighlight>
=={{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}}==
<
code::Vector{UInt8}
stack::Vector{Int32}
Line 8,505 ⟶ 8,973:
const vm = assemble(iob)
runvm(vm)
</
count is: 1
count is: 2
Line 8,519 ⟶ 8,987:
=={{header|M2000 Interpreter}}==
===Using Select Case===
<syntaxhighlight lang="m2000 interpreter">
Module Virtual_Machine_Interpreter (a$){
\\ function to extract string, replacing escape codes.
Line 8,692 ⟶ 9,160:
65 halt
}
</syntaxhighlight>
===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">
Module Virtual_Machine_Interpreter (a$){
\\ function to extract string, replacing escape codes.
Line 8,847 ⟶ 9,315:
65 halt
}
</syntaxhighlight>
=={{header|Mercury}}==
Line 8,860 ⟶ 9,328:
<
%%%
%%% The Rosetta Code Virtual Machine, in Mercury.
Line 9,751 ⟶ 10,219:
%%% prolog-indent-width: 2
%%% end:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</
Line 9,773 ⟶ 10,241:
=={{header|Nim}}==
<
type
Line 10,093 ⟶ 10,561:
vm.load(code)
vm.run()</
All tests passed.
=={{header|ObjectIcon}}==
<
#
# The Rosetta Code virtual machine in Object Icon.
Line 10,505 ⟶ 10,973:
exit(1)
end
end</
{{out}}
Line 10,521 ⟶ 10,989:
=={{header|Perl}}==
Tested with perl v5.26.1
<
# http://www.rosettacode.org/wiki/Compiler/virtual_machine_interpreter
Line 10,570 ⟶ 11,038:
}
$ops[vec($binary, $pc++, 8)][1]->() while 1; # run it</
Passes all tests.
=={{header|Phix}}==
Reusing cgen.e from the [[Compiler/code_generator#Phix|Code Generator task]]
<!--<
<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>
<!--</
{{out}}
<pre>
Line 10,633 ⟶ 11,101:
<
%%%
%%% The Rosetta Code Virtual Machine, for GNU Prolog.
Line 10,999 ⟶ 11,467:
%%% prolog-indent-width: 2
%%% end:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</
Line 11,016 ⟶ 11,484:
=={{header|Python}}==
Tested with Python 2.7 and 3.x
<
import sys, struct
Line 11,183 ⟶ 11,651:
data_size = load_code()
run_vm(data_size)</
=={{header|Racket}}==
Line 11,194 ⟶ 11,662:
<
;;;
;;; The Rosetta Code Virtual Machine, in Typed Racket.
Line 11,941 ⟶ 12,409:
(close-output-port outf))
(exit 0)))))</
Line 11,966 ⟶ 12,434:
{{trans|Perl}}
<syntaxhighlight lang="raku"
Datasize: 3 Strings: 2
"count is: "
Line 12,043 ⟶ 12,511:
$pc += $w;
%ops{%n2op{ $opcode }}();
}</
{{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.
{{works with|f2c|20100827}}
<
#
# The Rosetta Code code virtual machine in Ratfor 77.
Line 13,293 ⟶ 13,761:
end
######################################################################</
{{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].
<
package xyz.hyperreal.rosettacodeCompiler
Line 13,521 ⟶ 14,015:
}
</syntaxhighlight>
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.
<
package xyz.hyperreal
Line 13,553 ⟶ 14,047:
}
</syntaxhighlight>
=={{header|Scheme}}==
Line 13,561 ⟶ 14,055:
All of the "Compiler/Sample programs" are correctly interpreted.
<
(import (scheme base)
(scheme char)
Line 13,724 ⟶ 14,218:
(run-program data strings code))
(display "Error: pass a .asm filename\n"))
</syntaxhighlight>
=={{header|Wren}}==
Line 13,732 ⟶ 14,226:
{{libheader|Wren-fmt}}
{{libheader|Wren-ioutil}}
<
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())</
{{out}}
Line 14,014 ⟶ 14,508:
=={{header|Zig}}==
<
const std = @import("std");
Line 14,337 ⟶ 14,831:
}
}
</syntaxhighlight>
=={{header|zkl}}==
{{trans|Python}}
File rvm.zkl:
<
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);</
The binary code file code.bin:
{{out}}
|