mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
added arrow syntax for forcing output types and added the "any" type (which is basically useless and will likely change in the future)
This commit is contained in:
parent
efe8a177dc
commit
db0be51fa4
@ -1,8 +1,23 @@
|
|||||||
# mers statements overview
|
# Mers statements overview
|
||||||
|
|
||||||
This is the documentation for mers statements.
|
This is the documentation for mers statements.
|
||||||
In code, statements are represented by `SStatement`, `SStatementEnum`, `RStatement`, and `RStatementEnum`.
|
In code, statements are represented by `SStatement`, `SStatementEnum`, `RStatement`, and `RStatementEnum`.
|
||||||
|
|
||||||
|
## statement prefixes
|
||||||
|
|
||||||
|
A statement can be prefixed with any number of stars `*`. This is called dereferencing and turns a reference to a value into the value itself. Modifying the value after a dereference leaves the value the reference was pointing to untouched (the data will be cloned to achieve this).
|
||||||
|
|
||||||
|
A statement can also be prefixed with an arrow followed by the type the statement will have: `-> int/float 12`.
|
||||||
|
Although the statement will always return an `int`, mers will assume that it could also return a float.
|
||||||
|
If the statement's output doesn't fit in the forced type (`-> int "text"`), mers will generate an error.
|
||||||
|
In combination with functions, this is similar to rust's syntax:
|
||||||
|
|
||||||
|
fn my_func(a int, b int) -> int {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
# Different statements
|
||||||
|
|
||||||
## Value
|
## Value
|
||||||
|
|
||||||
A statement that always returns a certain value: `10`, `"Hello, World"`, ...
|
A statement that always returns a certain value: `10`, `"Hello, World"`, ...
|
||||||
|
3
examples/force_output_type.mers
Normal file
3
examples/force_output_type.mers
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn plus(a int, b int) -> int { a + b }
|
||||||
|
|
||||||
|
10.plus(20).debug()
|
13
examples/the_any_type.mers
Normal file
13
examples/the_any_type.mers
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
fn debug_any(val any) {
|
||||||
|
val.debug()
|
||||||
|
}
|
||||||
|
|
||||||
|
"something".debug_any()
|
||||||
|
|
||||||
|
fn just_return(val any) {
|
||||||
|
val
|
||||||
|
}.debug()
|
||||||
|
|
||||||
|
v := "text"
|
||||||
|
v.debug()
|
||||||
|
v.just_return().debug()
|
@ -979,7 +979,7 @@ impl BuiltinFunction {
|
|||||||
run_input_types.push(val.out_single());
|
run_input_types.push(val.out_single());
|
||||||
*var.lock().unwrap() = val;
|
*var.lock().unwrap() = val;
|
||||||
}
|
}
|
||||||
let out_type = f.out(&run_input_types);
|
let out_type = f.out(&run_input_types, &info);
|
||||||
let info = Arc::clone(info);
|
let info = Arc::clone(info);
|
||||||
let f = Arc::clone(f);
|
let f = Arc::clone(f);
|
||||||
VDataEnum::Thread(
|
VDataEnum::Thread(
|
||||||
|
@ -5,7 +5,15 @@ use crate::parsing::{
|
|||||||
parse::{self, ParseError, ScriptError},
|
parse::{self, ParseError, ScriptError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{code_runnable::RScript, val_data::VData};
|
use super::{code_parsed::SStatement, code_runnable::RScript, val_data::VData, val_type::VType};
|
||||||
|
|
||||||
|
// macro format is !(macro_type [...])
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Macro {
|
||||||
|
/// Compiles and executes the provided mers code at compile-time and inserts the value
|
||||||
|
StaticMers(VData),
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_macro(file: &mut File) -> Result<Macro, MacroError> {
|
pub fn parse_macro(file: &mut File) -> Result<Macro, MacroError> {
|
||||||
file.skip_whitespaces();
|
file.skip_whitespaces();
|
||||||
@ -63,12 +71,6 @@ fn parse_mers_code(file: &mut File) -> Result<RScript, MacroError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Macro {
|
|
||||||
/// Compiles and executes the provided mers code at compile-time and inserts the value
|
|
||||||
StaticMers(VData),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Macro {
|
impl Display for Macro {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -83,11 +83,11 @@ impl SBlock {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SFunction {
|
pub struct SFunction {
|
||||||
pub inputs: Vec<(String, VType)>,
|
pub inputs: Vec<(String, VType)>,
|
||||||
pub block: SBlock,
|
pub statement: SStatement,
|
||||||
}
|
}
|
||||||
impl SFunction {
|
impl SFunction {
|
||||||
pub fn new(inputs: Vec<(String, VType)>, block: SBlock) -> Self {
|
pub fn new(inputs: Vec<(String, VType)>, statement: SStatement) -> Self {
|
||||||
Self { inputs, block }
|
Self { inputs, statement }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,8 +268,9 @@ impl FormatGs for SStatement {
|
|||||||
}
|
}
|
||||||
// output self
|
// output self
|
||||||
if let Some(force_opt) = &self.force_output_type {
|
if let Some(force_opt) = &self.force_output_type {
|
||||||
write!(f, " -> ")?;
|
write!(f, "-> ")?;
|
||||||
force_opt.fmtgs(f, info, form, file)?;
|
force_opt.fmtgs(f, info, form, file)?;
|
||||||
|
write!(f, " ")?;
|
||||||
}
|
}
|
||||||
write!(f, "{}", "*".repeat(self.derefs))?;
|
write!(f, "{}", "*".repeat(self.derefs))?;
|
||||||
self.statement.fmtgs(f, info, form, file)?;
|
self.statement.fmtgs(f, info, form, file)?;
|
||||||
@ -293,14 +294,14 @@ impl FormatGs for SFunction {
|
|||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
for (i, (name, t)) in self.inputs.iter().enumerate() {
|
for (i, (name, t)) in self.inputs.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
write!(f, " {name}")?;
|
write!(f, " {name} ")?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{name} ")?;
|
write!(f, "{name} ")?;
|
||||||
}
|
}
|
||||||
t.fmtgs(f, info, form, file)?;
|
t.fmtgs(f, info, form, file)?;
|
||||||
}
|
}
|
||||||
write!(f, ") ")?;
|
write!(f, ") ")?;
|
||||||
self.block.fmtgs(f, info, form, file)
|
self.statement.fmtgs(f, info, form, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,13 +63,13 @@ pub struct RFunction {
|
|||||||
pub inputs: Vec<Arc<Mutex<VData>>>,
|
pub inputs: Vec<Arc<Mutex<VData>>>,
|
||||||
pub input_types: Vec<VType>,
|
pub input_types: Vec<VType>,
|
||||||
pub input_output_map: Vec<(Vec<VSingleType>, VType)>,
|
pub input_output_map: Vec<(Vec<VSingleType>, VType)>,
|
||||||
pub block: RBlock,
|
pub statement: RStatement,
|
||||||
}
|
}
|
||||||
impl RFunction {
|
impl RFunction {
|
||||||
pub fn run(&self, info: &GSInfo) -> VData {
|
pub fn run(&self, info: &GSInfo) -> VData {
|
||||||
self.block.run(info)
|
self.statement.run(info)
|
||||||
}
|
}
|
||||||
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
pub fn out(&self, input_types: &Vec<VSingleType>, info: &GlobalScriptInfo) -> VType {
|
||||||
self.input_output_map
|
self.input_output_map
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|v| {
|
.find_map(|v| {
|
||||||
@ -79,7 +79,7 @@ impl RFunction {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.expect("invalid args for function! possible issue with type-checker if this can be reached! feel free to report a bug.")
|
.unwrap_or_else(|| self.statement.out(info))
|
||||||
}
|
}
|
||||||
pub fn out_vt(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> VType {
|
pub fn out_vt(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> VType {
|
||||||
let mut out = VType { types: vec![] };
|
let mut out = VType { types: vec![] };
|
||||||
@ -92,10 +92,16 @@ impl RFunction {
|
|||||||
out = out | otype;
|
out = out | otype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if out.types.is_empty() {
|
||||||
|
// this can happen if we used the `any` type in our function signature,
|
||||||
|
// so in that case we just return the most broad type possible.
|
||||||
|
self.statement.out(info)
|
||||||
|
} else {
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pub fn out_all(&self, info: &GlobalScriptInfo) -> VType {
|
pub fn out_all(&self, info: &GlobalScriptInfo) -> VType {
|
||||||
self.block.out(info)
|
self.statement.out(info)
|
||||||
}
|
}
|
||||||
pub fn in_types(&self) -> &Vec<VType> {
|
pub fn in_types(&self) -> &Vec<VType> {
|
||||||
&self.input_types
|
&self.input_types
|
||||||
|
@ -263,12 +263,12 @@ fn get_all_functions(
|
|||||||
vartype.to()
|
vartype.to()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// block is parsed multiple times (this is why we get duplicates in stderr):
|
// the statement is parsed multiple times (this is why we get duplicates in stderr):
|
||||||
// - n times for the function args to generate the input-output map
|
// - n times for the function args to generate the input-output map
|
||||||
// - 1 more time here, where the function args aren't single types
|
// - 1 more time here, where the function args aren't single types
|
||||||
out.push((
|
out.push((
|
||||||
inputs.clone(),
|
inputs.clone(),
|
||||||
block(&s.block, ginfo, linfo.clone())?.out(ginfo),
|
statement(&s.statement, ginfo, &mut linfo.clone())?.out(ginfo),
|
||||||
));
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ fn function(
|
|||||||
inputs: input_vars,
|
inputs: input_vars,
|
||||||
input_types,
|
input_types,
|
||||||
input_output_map: all_outs,
|
input_output_map: all_outs,
|
||||||
block: block(&s.block, ginfo, linfo)?,
|
statement: statement(&s.statement, ginfo, &mut linfo.clone())?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +331,11 @@ pub fn stypes(t: &mut VType, ginfo: &mut GlobalScriptInfo) -> Result<(), ToRunna
|
|||||||
}
|
}
|
||||||
pub fn stype(t: &mut VSingleType, ginfo: &mut GlobalScriptInfo) -> Result<(), ToRunnableError> {
|
pub fn stype(t: &mut VSingleType, ginfo: &mut GlobalScriptInfo) -> Result<(), ToRunnableError> {
|
||||||
match t {
|
match t {
|
||||||
VSingleType::Bool | VSingleType::Int | VSingleType::Float | VSingleType::String => (),
|
VSingleType::Any
|
||||||
|
| VSingleType::Bool
|
||||||
|
| VSingleType::Int
|
||||||
|
| VSingleType::Float
|
||||||
|
| VSingleType::String => (),
|
||||||
VSingleType::Tuple(v) => {
|
VSingleType::Tuple(v) => {
|
||||||
for t in v {
|
for t in v {
|
||||||
stypes(t, ginfo)?;
|
stypes(t, ginfo)?;
|
||||||
@ -398,7 +402,7 @@ fn statement_adv(
|
|||||||
// eprintln!(" --> {}", t.0);
|
// eprintln!(" --> {}", t.0);
|
||||||
// }
|
// }
|
||||||
let mut state = match &*s.statement {
|
let mut state = match &*s.statement {
|
||||||
SStatementEnum::Value(v) => RStatementEnum::Value(v.clone()),
|
SStatementEnum::Value(v) => RStatementEnum::Value(v.clone()).to(),
|
||||||
SStatementEnum::Tuple(v) | SStatementEnum::List(v) => {
|
SStatementEnum::Tuple(v) | SStatementEnum::List(v) => {
|
||||||
let mut w = Vec::with_capacity(v.len());
|
let mut w = Vec::with_capacity(v.len());
|
||||||
let mut prev = None;
|
let mut prev = None;
|
||||||
@ -425,6 +429,7 @@ fn statement_adv(
|
|||||||
} else {
|
} else {
|
||||||
RStatementEnum::Tuple(w)
|
RStatementEnum::Tuple(w)
|
||||||
}
|
}
|
||||||
|
.to()
|
||||||
}
|
}
|
||||||
SStatementEnum::Variable(v, is_ref) => {
|
SStatementEnum::Variable(v, is_ref) => {
|
||||||
let existing_var = linfo.vars.get(v);
|
let existing_var = linfo.vars.get(v);
|
||||||
@ -465,6 +470,7 @@ fn statement_adv(
|
|||||||
} else {
|
} else {
|
||||||
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
||||||
}
|
}
|
||||||
|
.to()
|
||||||
}
|
}
|
||||||
SStatementEnum::FunctionCall(v, args) => {
|
SStatementEnum::FunctionCall(v, args) => {
|
||||||
let mut rargs = Vec::with_capacity(args.len());
|
let mut rargs = Vec::with_capacity(args.len());
|
||||||
@ -553,6 +559,7 @@ fn statement_adv(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.to(),
|
||||||
SStatementEnum::FunctionDefinition(name, f) => {
|
SStatementEnum::FunctionDefinition(name, f) => {
|
||||||
let f = Arc::new(function(f, ginfo, linfo.clone())?);
|
let f = Arc::new(function(f, ginfo, linfo.clone())?);
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
@ -564,9 +571,9 @@ fn statement_adv(
|
|||||||
linfo.fns.insert(name.clone(), vec![f]);
|
linfo.fns.insert(name.clone(), vec![f]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RStatementEnum::Value(VDataEnum::Function(f).to())
|
RStatementEnum::Value(VDataEnum::Function(f).to()).to()
|
||||||
}
|
}
|
||||||
SStatementEnum::Block(b) => RStatementEnum::Block(block(&b, ginfo, linfo.clone())?),
|
SStatementEnum::Block(b) => RStatementEnum::Block(block(&b, ginfo, linfo.clone())?).to(),
|
||||||
SStatementEnum::If(c, t, e) => RStatementEnum::If(
|
SStatementEnum::If(c, t, e) => RStatementEnum::If(
|
||||||
{
|
{
|
||||||
let condition = statement(&c, ginfo, linfo)?;
|
let condition = statement(&c, ginfo, linfo)?;
|
||||||
@ -591,8 +598,9 @@ fn statement_adv(
|
|||||||
Some(v) => Some(statement(&v, ginfo, linfo)?),
|
Some(v) => Some(statement(&v, ginfo, linfo)?),
|
||||||
None => None,
|
None => None,
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
SStatementEnum::Loop(c) => RStatementEnum::Loop(statement(&c, ginfo, linfo)?),
|
.to(),
|
||||||
|
SStatementEnum::Loop(c) => RStatementEnum::Loop(statement(&c, ginfo, linfo)?).to(),
|
||||||
SStatementEnum::For(v, c, b) => {
|
SStatementEnum::For(v, c, b) => {
|
||||||
let mut linfo = linfo.clone();
|
let mut linfo = linfo.clone();
|
||||||
let container = statement(&c, ginfo, &mut linfo)?;
|
let container = statement(&c, ginfo, &mut linfo)?;
|
||||||
@ -603,7 +611,7 @@ fn statement_adv(
|
|||||||
let assign_to = statement_adv(v, ginfo, &mut linfo, &mut Some((inner, &mut true)))?;
|
let assign_to = statement_adv(v, ginfo, &mut linfo, &mut Some((inner, &mut true)))?;
|
||||||
let block = statement(&b, ginfo, &mut linfo)?;
|
let block = statement(&b, ginfo, &mut linfo)?;
|
||||||
let o = RStatementEnum::For(assign_to, container, block);
|
let o = RStatementEnum::For(assign_to, container, block);
|
||||||
o
|
o.to()
|
||||||
}
|
}
|
||||||
|
|
||||||
SStatementEnum::Switch(switch_on, cases, force) => {
|
SStatementEnum::Switch(switch_on, cases, force) => {
|
||||||
@ -639,7 +647,7 @@ fn statement_adv(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RStatementEnum::Switch(switch_on, ncases, *force)
|
RStatementEnum::Switch(switch_on, ncases, *force).to()
|
||||||
}
|
}
|
||||||
SStatementEnum::Match(cases) => {
|
SStatementEnum::Match(cases) => {
|
||||||
let mut ncases: Vec<(RStatement, RStatement, RStatement)> =
|
let mut ncases: Vec<(RStatement, RStatement, RStatement)> =
|
||||||
@ -667,13 +675,13 @@ fn statement_adv(
|
|||||||
out_type = out_type | VSingleType::Tuple(vec![]).to();
|
out_type = out_type | VSingleType::Tuple(vec![]).to();
|
||||||
}
|
}
|
||||||
|
|
||||||
RStatementEnum::Match(ncases)
|
RStatementEnum::Match(ncases).to()
|
||||||
}
|
}
|
||||||
|
|
||||||
SStatementEnum::IndexFixed(st, i) => {
|
SStatementEnum::IndexFixed(st, i) => {
|
||||||
let st = statement(st, ginfo, linfo)?;
|
let st = statement(st, ginfo, linfo)?;
|
||||||
if st.out(ginfo).get_always(*i, ginfo).is_some() {
|
if st.out(ginfo).get_always(*i, ginfo).is_some() {
|
||||||
RStatementEnum::IndexFixed(st, *i)
|
RStatementEnum::IndexFixed(st, *i).to()
|
||||||
} else {
|
} else {
|
||||||
return Err(ToRunnableError::NotIndexableFixed(st.out(ginfo), *i));
|
return Err(ToRunnableError::NotIndexableFixed(st.out(ginfo), *i));
|
||||||
}
|
}
|
||||||
@ -689,7 +697,8 @@ fn statement_adv(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
statement(s, ginfo, linfo)?,
|
statement(s, ginfo, linfo)?,
|
||||||
),
|
)
|
||||||
|
.to(),
|
||||||
SStatementEnum::TypeDefinition(name, t) => {
|
SStatementEnum::TypeDefinition(name, t) => {
|
||||||
// insert to name map has to happen before stypes()
|
// insert to name map has to happen before stypes()
|
||||||
ginfo
|
ginfo
|
||||||
@ -698,13 +707,12 @@ fn statement_adv(
|
|||||||
let mut t = t.to_owned();
|
let mut t = t.to_owned();
|
||||||
stypes(&mut t, ginfo)?;
|
stypes(&mut t, ginfo)?;
|
||||||
ginfo.custom_types.push(t);
|
ginfo.custom_types.push(t);
|
||||||
RStatementEnum::Value(VDataEnum::Tuple(vec![]).to())
|
RStatementEnum::Value(VDataEnum::Tuple(vec![]).to()).to()
|
||||||
}
|
}
|
||||||
SStatementEnum::Macro(m) => match m {
|
SStatementEnum::Macro(m) => match m {
|
||||||
Macro::StaticMers(val) => RStatementEnum::Value(val.clone()),
|
Macro::StaticMers(val) => RStatementEnum::Value(val.clone()).to(),
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
.to();
|
|
||||||
state.derefs = s.derefs;
|
state.derefs = s.derefs;
|
||||||
// if force_output_type is set, verify that the real output type actually fits in the forced one.
|
// if force_output_type is set, verify that the real output type actually fits in the forced one.
|
||||||
if let Some(force_opt) = &s.force_output_type {
|
if let Some(force_opt) = &s.force_output_type {
|
||||||
|
@ -18,6 +18,7 @@ pub struct VType {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum VSingleType {
|
pub enum VSingleType {
|
||||||
|
Any,
|
||||||
Bool,
|
Bool,
|
||||||
Int,
|
Int,
|
||||||
Float,
|
Float,
|
||||||
@ -37,7 +38,8 @@ impl VSingleType {
|
|||||||
/// None => Cannot get, Some(t) => getting can return t or nothing
|
/// None => Cannot get, Some(t) => getting can return t or nothing
|
||||||
pub fn get(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
|
pub fn get(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool
|
Self::Any
|
||||||
|
| Self::Bool
|
||||||
| Self::Int
|
| Self::Int
|
||||||
| Self::Float
|
| Self::Float
|
||||||
| Self::Function(..)
|
| Self::Function(..)
|
||||||
@ -56,7 +58,8 @@ impl VSingleType {
|
|||||||
}
|
}
|
||||||
pub fn get_ref(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
|
pub fn get_ref(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool
|
Self::Any
|
||||||
|
| Self::Bool
|
||||||
| Self::Int
|
| Self::Int
|
||||||
| Self::Float
|
| Self::Float
|
||||||
| Self::Function(..)
|
| Self::Function(..)
|
||||||
@ -76,7 +79,8 @@ impl VSingleType {
|
|||||||
/// None => might not always return t, Some(t) => can only return t
|
/// None => might not always return t, Some(t) => can only return t
|
||||||
pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
|
pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool
|
Self::Any
|
||||||
|
| Self::Bool
|
||||||
| Self::Int
|
| Self::Int
|
||||||
| Self::Float
|
| Self::Float
|
||||||
| Self::String
|
| Self::String
|
||||||
@ -95,7 +99,8 @@ impl VSingleType {
|
|||||||
}
|
}
|
||||||
pub fn get_always_ref(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
|
pub fn get_always_ref(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool
|
Self::Any
|
||||||
|
| Self::Bool
|
||||||
| Self::Int
|
| Self::Int
|
||||||
| Self::Float
|
| Self::Float
|
||||||
| Self::String
|
| Self::String
|
||||||
@ -179,7 +184,12 @@ impl VType {
|
|||||||
impl VSingleType {
|
impl VSingleType {
|
||||||
pub fn get_any(&self, info: &GlobalScriptInfo) -> Option<VType> {
|
pub fn get_any(&self, info: &GlobalScriptInfo) -> Option<VType> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
|
Self::Any
|
||||||
|
| Self::Bool
|
||||||
|
| Self::Int
|
||||||
|
| Self::Float
|
||||||
|
| Self::Function(..)
|
||||||
|
| Self::Thread(..) => None,
|
||||||
Self::String => Some(VSingleType::String.into()),
|
Self::String => Some(VSingleType::String.into()),
|
||||||
Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)),
|
Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)),
|
||||||
Self::List(t) => Some(t.clone()),
|
Self::List(t) => Some(t.clone()),
|
||||||
@ -192,7 +202,12 @@ impl VSingleType {
|
|||||||
}
|
}
|
||||||
pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> {
|
pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
|
Self::Any
|
||||||
|
| Self::Bool
|
||||||
|
| Self::Int
|
||||||
|
| Self::Float
|
||||||
|
| Self::Function(..)
|
||||||
|
| Self::Thread(..) => None,
|
||||||
Self::String => Some(VSingleType::String.into()),
|
Self::String => Some(VSingleType::String.into()),
|
||||||
Self::Tuple(t) => Some(
|
Self::Tuple(t) => Some(
|
||||||
t.iter()
|
t.iter()
|
||||||
@ -378,7 +393,7 @@ impl VSingleType {
|
|||||||
/// converts all Self::EnumVariantS to Self::EnumVariant
|
/// converts all Self::EnumVariantS to Self::EnumVariant
|
||||||
pub fn enum_variants(&mut self, enum_variants: &mut HashMap<String, usize>) {
|
pub fn enum_variants(&mut self, enum_variants: &mut HashMap<String, usize>) {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool | Self::Int | Self::Float | Self::String => (),
|
Self::Any | Self::Bool | Self::Int | Self::Float | Self::String => (),
|
||||||
Self::Tuple(v) => {
|
Self::Tuple(v) => {
|
||||||
for t in v {
|
for t in v {
|
||||||
t.enum_variants(enum_variants);
|
t.enum_variants(enum_variants);
|
||||||
@ -412,6 +427,8 @@ impl VSingleType {
|
|||||||
}
|
}
|
||||||
pub fn fits_in(&self, rhs: &Self, info: &GlobalScriptInfo) -> bool {
|
pub fn fits_in(&self, rhs: &Self, info: &GlobalScriptInfo) -> bool {
|
||||||
let o = match (self, rhs) {
|
let o = match (self, rhs) {
|
||||||
|
(_, Self::Any) => true,
|
||||||
|
(Self::Any, _) => false,
|
||||||
(Self::Reference(r), Self::Reference(b)) => r.fits_in(b, info),
|
(Self::Reference(r), Self::Reference(b)) => r.fits_in(b, info),
|
||||||
(Self::Reference(_), _) | (_, Self::Reference(_)) => false,
|
(Self::Reference(_), _) | (_, Self::Reference(_)) => false,
|
||||||
(Self::EnumVariant(v1, t1), Self::EnumVariant(v2, t2)) => {
|
(Self::EnumVariant(v1, t1), Self::EnumVariant(v2, t2)) => {
|
||||||
@ -526,6 +543,7 @@ impl FormatGs for VSingleType {
|
|||||||
file: Option<&crate::parsing::file::File>,
|
file: Option<&crate::parsing::file::File>,
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Self::Any => write!(f, "any"),
|
||||||
Self::Bool => write!(f, "bool"),
|
Self::Bool => write!(f, "bool"),
|
||||||
Self::Int => write!(f, "int"),
|
Self::Int => write!(f, "int"),
|
||||||
Self::Float => write!(f, "float"),
|
Self::Float => write!(f, "float"),
|
||||||
@ -649,7 +667,7 @@ impl FormatGs for VType {
|
|||||||
}
|
}
|
||||||
t.fmtgs(f, info, form, file)?;
|
t.fmtgs(f, info, form, file)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
write!(f, ",")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Display for VType {
|
impl Display for VType {
|
||||||
|
@ -390,6 +390,7 @@ impl ByteData for VType {
|
|||||||
impl ByteDataA for VSingleType {
|
impl ByteDataA for VSingleType {
|
||||||
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
||||||
match self {
|
match self {
|
||||||
|
Self::Any => vec.push(b'a'),
|
||||||
Self::Bool => vec.push(b'b'),
|
Self::Bool => vec.push(b'b'),
|
||||||
Self::Int => vec.push(b'i'),
|
Self::Int => vec.push(b'i'),
|
||||||
Self::Float => vec.push(b'f'),
|
Self::Float => vec.push(b'f'),
|
||||||
@ -438,6 +439,7 @@ impl ByteData for VSingleType {
|
|||||||
let mut switch_byte = [0u8];
|
let mut switch_byte = [0u8];
|
||||||
data.read_exact(&mut switch_byte)?;
|
data.read_exact(&mut switch_byte)?;
|
||||||
Ok(match switch_byte[0] {
|
Ok(match switch_byte[0] {
|
||||||
|
b'a' => Self::Any,
|
||||||
b'b' => Self::Bool,
|
b'b' => Self::Bool,
|
||||||
b'i' => Self::Int,
|
b'i' => Self::Int,
|
||||||
b'f' => Self::Float,
|
b'f' => Self::Float,
|
||||||
|
@ -192,7 +192,7 @@ pub fn parse_step_interpret(
|
|||||||
"args".to_string(),
|
"args".to_string(),
|
||||||
VSingleType::List(VSingleType::String.into()).to(),
|
VSingleType::List(VSingleType::String.into()).to(),
|
||||||
)],
|
)],
|
||||||
parse_block_advanced(file, Some(false), true, true, false)?,
|
SStatementEnum::Block(parse_block_advanced(file, Some(false), false, true, false)?).to(),
|
||||||
);
|
);
|
||||||
if ginfo.log.after_parse.log() {
|
if ginfo.log.after_parse.log() {
|
||||||
ginfo.log.log(LogMsg::AfterParse(
|
ginfo.log.log(LogMsg::AfterParse(
|
||||||
@ -543,6 +543,18 @@ pub mod implementation {
|
|||||||
) -> Result<SStatement, ParseError> {
|
) -> Result<SStatement, ParseError> {
|
||||||
file.skip_whitespaces();
|
file.skip_whitespaces();
|
||||||
let err_start_of_statement = *file.get_pos();
|
let err_start_of_statement = *file.get_pos();
|
||||||
|
// force output type
|
||||||
|
let force_opt = if file[file.get_pos().current_char_index..].starts_with("->") {
|
||||||
|
file.next();
|
||||||
|
file.next();
|
||||||
|
file.skip_whitespaces();
|
||||||
|
let o = parse_type(file)?;
|
||||||
|
file.skip_whitespaces();
|
||||||
|
Some(o)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
// derefs
|
||||||
let mut derefs = 0;
|
let mut derefs = 0;
|
||||||
loop {
|
loop {
|
||||||
if let Some('*') = file.peek() {
|
if let Some('*') = file.peek() {
|
||||||
@ -836,6 +848,7 @@ pub mod implementation {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
out.derefs = derefs;
|
out.derefs = derefs;
|
||||||
|
out.force_output_type = force_opt;
|
||||||
let err_end_of_original_statement = *file.get_pos();
|
let err_end_of_original_statement = *file.get_pos();
|
||||||
// special characters that can follow a statement (loop because these can be chained)
|
// special characters that can follow a statement (loop because these can be chained)
|
||||||
loop {
|
loop {
|
||||||
@ -1070,6 +1083,7 @@ pub mod implementation {
|
|||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
let mut arg_name = String::new();
|
let mut arg_name = String::new();
|
||||||
|
file.skip_whitespaces();
|
||||||
loop {
|
loop {
|
||||||
let err_fn_arg_name_start = *file.get_pos();
|
let err_fn_arg_name_start = *file.get_pos();
|
||||||
match file.next() {
|
match file.next() {
|
||||||
@ -1100,7 +1114,7 @@ pub mod implementation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(SFunction::new(args, parse_block(file)?))
|
Ok(SFunction::new(args, parse_statement(file)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_type(file: &mut File) -> Result<VType, ParseError> {
|
pub(crate) fn parse_type(file: &mut File) -> Result<VType, ParseError> {
|
||||||
@ -1122,7 +1136,6 @@ pub mod implementation {
|
|||||||
closed_fn_args = true;
|
closed_fn_args = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
file.skip_whitespaces();
|
|
||||||
match file.peek() {
|
match file.peek() {
|
||||||
Some('/') => {
|
Some('/') => {
|
||||||
file.next();
|
file.next();
|
||||||
@ -1132,8 +1145,15 @@ pub mod implementation {
|
|||||||
file.next();
|
file.next();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(_) => break,
|
Some(ch) if ch.is_whitespace() => break,
|
||||||
|
Some(ch) if ch == ',' => {
|
||||||
|
file.next();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Some(ch) => {
|
||||||
|
eprintln!("[warn] stopped parsing type at character {ch} (unexpected character, moving on...)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1201,8 +1221,7 @@ pub mod implementation {
|
|||||||
let mut name = ch.to_string();
|
let mut name = ch.to_string();
|
||||||
loop {
|
loop {
|
||||||
match file.peek() {
|
match file.peek() {
|
||||||
Some(']') => break,
|
Some(']' | '/' | ',') => break,
|
||||||
Some('/') => break,
|
|
||||||
Some(')') if in_fn_args => {
|
Some(')') if in_fn_args => {
|
||||||
file.next();
|
file.next();
|
||||||
closed_bracket_in_fn_args = true;
|
closed_bracket_in_fn_args = true;
|
||||||
@ -1315,6 +1334,7 @@ pub mod implementation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match name.trim().to_lowercase().as_str() {
|
match name.trim().to_lowercase().as_str() {
|
||||||
|
"any" => VSingleType::Any,
|
||||||
"bool" => VSingleType::Bool,
|
"bool" => VSingleType::Bool,
|
||||||
"int" => VSingleType::Int,
|
"int" => VSingleType::Int,
|
||||||
"float" => VSingleType::Float,
|
"float" => VSingleType::Float,
|
||||||
|
Loading…
Reference in New Issue
Block a user