Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/limuy2022/trc
Browse files Browse the repository at this point in the history
  • Loading branch information
limuy2022 committed Jan 20, 2024
2 parents 228973f + 016498a commit 83c404e
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 28 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Trc is a stack-based programming language

Trc's syntax is easy,and have full toolchain.It is easy to learn modern c++ and compiler,too.
Trc's syntax is easy,and have full toolchain. It is easy to learn modern c++ and compiler,too.

## language

Expand Down Expand Up @@ -81,6 +81,8 @@ Wechat:angelgel2020

QQ:3570249647

email: ```[email protected]```

## Referenced Open-source software

| Library |Usage |
Expand Down
7 changes: 7 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ rand = "0.8.5"
clap = { version = "4.4.18", features = ["derive"] }
gettext-rs = "0.7.0"
colored = "2.1.0"
downcast-rs = "1.2.0"
6 changes: 6 additions & 0 deletions rust/locales/zh_CN/LC_MESSAGES/trans.po
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ msgstr "语法错误"
msgid "OperatorError"
msgstr "操作符错误"

msgid "VmError"
msgstr "虚拟机错误"

msgid "this string should be ended with {}"
msgstr "这个字符串应当以{}结束"

msgid "operator {} is not supported for type {}"
msgstr "操作符{}不支持类型{}"

msgid "The number of data of vm stack is not correct, should have {} data"
msgstr "虚拟机栈中数据数量不正确,期望有{}个数据"
6 changes: 6 additions & 0 deletions rust/src/base/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ const EXIT_FAILURE: i32 = 1;

pub const SYNTAX_ERROR: &str = "SyntaxError";
pub const OPERATOR_ERROR: &str = "OperatorError";
pub const VM_ERROR:&str = "VmError";

pub const STRING_WITHOUT_END: &str = "this string should be ended with {}";
pub const OPERATOR_IS_NOT_SUPPORT: &str = "operator {} is not supported for type {}";
pub const VM_DATA_NUMBER:&str = "The number of data of vm stack is not correct, should have {} data";

pub struct ErrorInfo {
pub message: String,
Expand All @@ -28,6 +31,9 @@ pub trait ErrorContent {
fn get_line(&self) -> usize;
}

/// report error in vm or compiler
/// we will translate the error type to gettextrs
/// but you should translate the error messgae by caller
pub fn report_error(content: &impl ErrorContent, info: ErrorInfo) {
eprintln!("Error in line {}", content.get_line());
eprintln!("In module {}", content.get_module_name());
Expand Down
3 changes: 0 additions & 3 deletions rust/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ impl TokenIo for FileSource {
pub struct Compiler {
// to support read from stdin and file
input: Box<dyn TokenIo>,
line: usize,
const_pool: ValuePool,
option: Option,
content: Content,
Expand All @@ -229,7 +228,6 @@ impl Compiler {
let f = std::fs::File::open(filename);
Compiler {
input: Box::new(FileSource::new(f.unwrap())),
line: 1,
const_pool: ValuePool::new(),
option,
content: Content::new(cfg::MAIN_MODULE_NAME),
Expand All @@ -244,7 +242,6 @@ impl Compiler {
fn new_string_compiler(option: Option, source: &str) -> Self {
Compiler {
input: Box::new(StringSource::new(String::from(source))),
line: 1,
const_pool: ValuePool::new(),
option,
content: Content::new(cfg::MAIN_MODULE_NAME),
Expand Down
102 changes: 100 additions & 2 deletions rust/src/compiler/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,45 @@ enum TokenType {
MOD,
// //
EXACT_DIVISION,
// +=
SELF_ADD,
// -=
SELF_SUB,
// *=
SELF_MUL,
// /=
SELF_DIV,
// //=
SELF_EXTRA_DIV,
// %=
SELF_MOD,
// **
POWER,
// **=
SELF_POWER,
INT_VALUE,
STRING_VALUE,
FLOAT_VALUE,
LONG_INT_VALUE,
LONG_FLOAT_VALUE,
// =
ASSIGN,
// :=
STORE,
// ==
EQUAL,
// !=
UNEQUAL,
// >
GREATER,
// <
LESS,
// <=
LESS_EQUAL,
// >=
GREATER_EQUAL,
// !
NOT,
}

#[derive(PartialEq, Debug)]
Expand Down Expand Up @@ -75,6 +109,37 @@ impl Iterator for TokenLex<'_> {
}
}

macro_rules! binary_symbol {
($a:expr, $b:expr, $binary_sym:expr, $sself:expr) => {{
let c = $sself.compiler_data.input.read();
if c == $binary_sym {
return Token::new($b, None)
}
$sself.compiler_data.input.unread(c);
Token::new($a, None)
}}
}

macro_rules! self_symbol {
($sym:expr, $self_sym:expr, $sself:expr) =>
{{
binary_symbol!($sym, $self_sym, '=', $sself)
}}
}

macro_rules! double_symbol {
($before_sym:expr, $before_self_sym:expr, $matched_sym:expr, $matched_self_sym:expr, matched_char:expr, $sself:expr) => {
{
let c = $sself.compiler_data.input.read();
if c == $matched_char {
return self_symbol!($matched_sym, $matched_self_sym, self)
}
self.compiler_data.input.unread(c);
return self_symbol!($before_sym, $before_self_sym, self);
}
};
}

impl TokenLex<'_> {
pub fn new<'a>(compiler_data: &'a mut Compiler) -> TokenLex<'a> {
TokenLex { compiler_data }
Expand All @@ -90,6 +155,29 @@ impl TokenLex<'_> {
']' => Token::new(TokenType::RIGHT_MIDDLE_BRACE, None),
'(' => Token::new(TokenType::LEFT_SMALL_BRACE, None),
')' => Token::new(TokenType::RIGHT_SMALL_BRACE, None),
'+' => self_symbol!(TokenType::ADD, TokenType::SELF_ADD, self),
'-' => self_symbol!(TokenType::SUB, TokenType::SELF_SUB, self),
'*' => {
let c = self.compiler_data.input.read();
if c == '*' {
return self_symbol!(TokenType::POWER, TokenType::SELF_POWER, self)
}
self.compiler_data.input.unread(c);
return self_symbol!(TokenType::MUL, TokenType::SELF_MUL, self);
},
'%' => self_symbol!(TokenType::MOD, TokenType::SELF_MOD, self),
'/' => {
let c = self.compiler_data.input.read();
if c == '=' {
return Token::new(TokenType::SELF_DIV, None)
}
self.compiler_data.input.unread(c);
Token::new(TokenType::DIV, None)
},
'=' => binary_symbol!(TokenType::ASSIGN, TokenType::EQUAL, '=', self),
'!' => binary_symbol!(TokenType::NOT, TokenType::UNEQUAL, '=', self),
'>' => binary_symbol!(TokenType::GREATER, TokenType::GREATER_EQUAL, '=', self),
'<' => binary_symbol!(TokenType::LESS, TokenType::LESS_EQUAL, '=', self),
_ => panic!("Not a symbol.Compiler error"),
}
}
Expand Down Expand Up @@ -191,7 +279,7 @@ impl TokenLex<'_> {
continue;
}
'\n' => {
self.compiler_data.line += 1;
self.compiler_data.content.add_line();
}
_ => break,
},
Expand Down Expand Up @@ -251,7 +339,17 @@ mod tests {
}

#[test]
fn test_symbol_lex() {}
fn test_symbol_lex() {
let mut env = Compiler::new_string_compiler(
Option::new(false, InputSource::StringInternal),
r#":{}[]()+=%=//= // /=** *=*"#,
);
let mut t = TokenLex::new(&mut env);
let res = vec![
Token::new(TokenType::STRING_VALUE, Some(Data::Ind(0)))
];
check(&mut t, res);
}

#[test]
fn test_string_lex() {
Expand Down
52 changes: 44 additions & 8 deletions rust/src/tvm.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
mod algo;
mod function;
mod types;
mod def;

use clap::error;
use gettextrs::gettext;

use crate::{
base::error::ErrorContent,
base::error::{ErrorContent, report_error, ErrorInfo, VM_DATA_NUMBER, VM_ERROR},
cfg,
};

Expand Down Expand Up @@ -88,6 +92,7 @@ enum Opcode {
Sub,
Mul,
Div,
ExtraDiv,
Mod,
Eq,
Ne,
Expand All @@ -104,6 +109,30 @@ enum Opcode {
PopFrame,
// create a frame to hold the function
NewFrame,
// Load a int from const pool
LoadInt
}

/// reduce the duplicate code to solve the operator running
macro_rules! OP {
($trait_used:ident, $sself:expr) => {{
let t1 = $sself.dynadata.obj_stack.pop();
let t2 = $sself.dynadata.obj_stack.pop();
if t1.is_none() || t2.is_none() {
report_error(&$sself.run_contnet, ErrorInfo::new(gettext!(VM_DATA_NUMBER, 2), VM_ERROR));
}
let t1 = t1.unwrap();
let t2 = t2.unwrap();
let ret = t1.$trait_used(t2);
match ret {
Err(e) => {
report_error(&$sself.run_contnet, e);
},
Ok(t) => {
$sself.dynadata.obj_stack.push(t);
}
}
}};
}

impl<'a> Vm<'a> {
Expand All @@ -121,13 +150,20 @@ impl<'a> Vm<'a> {
pub fn run(&mut self) {
while self.pc < self.inst.len() {
match self.inst[self.pc].opcode {
Opcode::Add => {
let t1 = self.dynadata.obj_stack.pop();
let t2 = self.dynadata.obj_stack.pop();
if t1.is_none() || t2.is_none() {}
}
Opcode::Div => {}
Opcode::Gt => {}
Opcode::Add => OP!(add, self),
Opcode::Sub => OP!(sub, self),
Opcode::Mul => OP!(mul, self),
Opcode::Div => OP!(div, self),
Opcode::ExtraDiv => OP!(extra_div, self),
Opcode::Mod => OP!(modd, self),
Opcode::Gt => OP!(gt, self),
Opcode::Lt => OP!(lt, self),
Opcode::Ge => OP!(ge, self),
Opcode::Le => OP!(le, self),
Opcode::Eq => OP!(eq, self),
Opcode::Ne => OP!(ne, self),
Opcode::And => OP!(and, self),
Opcode::Or => OP!(or, self),
Opcode::NewFrame => {}
Opcode::PopFrame => {
self.dynadata.frames_stack.pop();
Expand Down
Empty file added rust/src/tvm/def.rs
Empty file.
2 changes: 2 additions & 0 deletions rust/src/tvm/function.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use super::types::TrcObj;

pub struct Func {
name: String,
}
Expand Down
Loading

0 comments on commit 83c404e

Please sign in to comment.