Nanoparrot

From perl6.cz

Ukázka jedné z možností (CGOTO core) jak virtuální stroj Parrot interpretuje bytekód.

Source for nanoparrot.c: examples/c/nanoparrot.c

 gcc -E nanoparrot.c > nanoparrot-prep.c
 vim nanoparrot-prep.c
 cat nanoparrot-prep.c
/*
 * Copyright (C) 2001-2006, The Perl Foundation.
 * $Id: mj%20and%20Parrot%3A%20nanoparrot,v 1.1 2006/06/17 11:17:46 nobody Exp nobody $
 *
 * - demonstrates how the interpreter interprets bytecode
 *   its vastly simplified but the very basics are the same
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// 26 "nanoparrot.c" 2

typedef int INTVAL;
typedef int opcode_t;
typedef double FLOATVAL;
typedef void PMC;
typedef void STRING;

struct Reg {
	INTVAL int_reg;
	FLOATVAL num_reg;
	STRING *string_reg;
	PMC *pmc_reg;
};

// 54 "nanoparrot.c"
struct pf {
	opcode_t *byte_code;
	char **const_table;
};

typedef struct Interp {
	struct Reg *bp;
	struct pf *code;
	opcode_t *(**op_func)(opcode_t *, struct Interp*);
	const char **op_info;
	int flags;
} Interp;

// 84 "nanoparrot.c"
typedef enum {
	OP_end,
	OP_print_sc,
	OP_print_i,
	OP_set_i_ic,
	OP_if_i_ic,
	OP_sub_i_i_i,
	OP_MAX
} opcodes;

// 155 "nanoparrot.c"
static void run(Interp *interpreter, opcode_t *pc) {
	static void *labels[] = {
		&&lOP_end,
		&&lOP_print_sc,
		&&lOP_print_i,
		&&lOP_set_i_ic,
		&&lOP_if_i_ic,
		&&lOP_sub_i_i_i,
		&&lOP_MAX
	};

	// 174 "nanoparrot.c"
	goto *labels[*pc];

	lOP_end:
		return;
	lOP_print_sc:
		printf("%s", interpreter->code->const_table[pc[1]]);
		pc += 2;
		goto *labels[*pc];
	lOP_print_i:
		printf("%d", interpreter->bp[pc[1]].int_reg);
		pc += 2;
		goto *labels[*pc];
	lOP_set_i_ic:
		interpreter->bp[pc[1]].int_reg = pc[2];
		pc += 3;
		goto *labels[*pc];
	lOP_if_i_ic:
		if (interpreter->bp[pc[1]].int_reg)
			pc += pc[2];
		else
			pc += 3;
		goto *labels[*pc];
	lOP_sub_i_i_i:
		interpreter->bp[pc[1]].int_reg = 
                    interpreter->bp[pc[2]].int_reg - interpreter->bp[pc[3]].int_reg;
		pc += 4;
		goto *labels[*pc];
	lOP_MAX:
		printf("illegal opcode\n");
		exit(1);
		goto *labels[*pc];

}

// 215 "nanoparrot.c"
static void
init(Interp *interpreter, opcode_t *prog) {
	interpreter->bp = calloc(32, sizeof(struct Reg));

	interpreter->op_func = malloc(OP_MAX * sizeof(void*));
	interpreter->op_info = malloc(OP_MAX * sizeof(char*));

	interpreter->op_info[OP_end] = "end";
	interpreter->op_info[OP_print_sc] = "print_sc";
	interpreter->op_info[OP_print_i] = "print_i";
	interpreter->op_info[OP_set_i_ic] = "set_i_ic";
	interpreter->op_info[OP_if_i_ic] = "if_i_ic";
	interpreter->op_info[OP_sub_i_i_i] = "sub_i_i_i";

	interpreter->code = malloc(sizeof(struct pf));
	interpreter->code->byte_code = prog;

	interpreter->code->const_table = malloc(4 * sizeof(char*));
	interpreter->code->const_table[0] = "\n";
	interpreter->code->const_table[1] = "done\n";
	interpreter->code->const_table[2] = "error\n";
	interpreter->code->const_table[3] = "usage: ./nanoparrot mops\n";
}

int main(int argc, char *argv[]) {
	opcode_t *prog;

	opcode_t mops[] = {
		OP_set_i_ic, 4, 1000000000,
		OP_print_i, 4,
		OP_print_sc, 0,
		OP_set_i_ic, 5, 1,
		OP_sub_i_i_i, 4, 4, 5,
		OP_if_i_ic, 4, -4,
		OP_print_sc, 1,
		OP_end
	};

	opcode_t usage[] = {
		OP_set_i_ic, 0, 2,
		OP_if_i_ic, 0, 6,
		OP_print_sc, 2,
		OP_end,
		OP_print_sc, 3,
		OP_end
 	};
	Interp *interpreter = malloc(sizeof(Interp));

	prog = usage;
	if (argc > 1) {
		if (!strcmp(argv[1], "mops"))
			prog = mops;
	}
	init(interpreter, prog);
	run(interpreter, prog);
	return 0;
}

real PASM - Parrot assembler

cat nanoparrot.pasm
    set I4, 1000000000
    print I4
    print "\n"
    set I5, 1

LABEL_MINUS4:
    sub I4, I4, I5
    ne I4, 0, LABEL_MINUS4

    print "\n"
    end

nanoparrot mops for perl users:

cat nanoparrot.pl
 $I4 = 1_000_000_000;
 print $I4;
 print "\n";
 $I5 = 1;
 LABEL_MINUS4:
     $I4 = $I4 - $I5;
 goto LABEL_MINUS4 if $I4;
 print "\n";
 exit(0);

and "benchmarks":

 cat /proc/cpuinfo | grep -P "bogomips|cpu MHz|processor"
 processor       : 0
 cpu MHz         : 3000.267
 bogomips        : 5914.62
 processor       : 1
 cpu MHz         : 3000.267
 bogomips        : 5980.16
gcc -o nanoparrot-prep -Wall nanoparrot-prep.c -O3 && time ./nanoparrot-prep mops
 real    0m7.155s
 user    0m7.105s
 sys     0m0.007s
./parrot --version && time ./parrot ./nanoparrot.pasm && time ./parrot -j ./nanoparrot.pasm
 Parrot 0.4.4-devel (r12885)

 real    0m38.742s
 user    0m38.718s
 sys     0m0.020s

 real    0m0.519s
 user    0m0.511s
 sys     0m0.008s
time perl ./nanoparrot.pl
 real    5m22.974s
 user    5m22.942s
 sys     0m0.051s

Externí odkazy

Personal tools
Language