jsonpiler 0.10.4

a Json syntax programming language for Windows
Documentation
use crate::prelude::*;
const ENTER: &str = "EnterCriticalSection";
const LEAVE: &str = "LeaveCriticalSection";
impl Jsonpiler {
  pub(crate) fn assign(
    &mut self,
    is_global_opt: Option<bool>,
    (var, val): KeyVal,
    scope: &mut Scope,
  ) -> ErrOR<bool> {
    let reassign = if let Some(is_g) = is_global_opt {
      self.check_defined(&var, var.pos, scope)?;
      Err(is_g)
    } else {
      let variable = self.get_var(&var, scope)?.val;
      if variable.val.as_type() != val.val.as_type() {
        return Err(type_err(
          format_variable(&var.val, variable.kind),
          vec![variable.val.as_type()],
          val.map_ref(Json::as_type),
        ));
      }
      Ok(
        variable
          .val
          .memory()
          .ok_or_else(|| Compilation(UndefinedVar(var.val.clone()), vec![var.pos]))?,
      )
    };
    let is_global = reassign.is_err_and(|is_g| is_g);
    let call_once = scope.loop_labels.is_empty() && scope.epilogue.is_none();
    let data_sect = is_global && call_once;
    let value = match &val.val {
      Bool(Lit(lit)) if data_sect => Bool(Var(self.global_b(*lit))),
      Int(Lit(int)) if data_sect => Int(Var(self.global_q(int.cast_unsigned()))),
      Float(Lit(lit)) if data_sect => Float(Var(self.global_q(lit.to_bits()))),
      Null(_) | Array(_) | Bool(_) | Float(_) | Int(_) | Object(_) | Str(_) => {
        if is_global {
          self.critical_sect(scope, ENTER);
        }
        let val_type = val.val.as_type();
        let size = val_type.mem_type(val.pos)?.size();
        let memory = match reassign {
          Ok(memory) => {
            self.heap_free(memory, scope);
            memory
          }
          Err(is_g) => Memory(
            if is_g {
              Global(self.bss(u32::try_from(size)?, u32::try_from(size)?))
            } else {
              Local(Long, scope.alloc(size, size)?)
            },
            MemoryType {
              heap: Value,
              size: Small(match size {
                1 => RB,
                4 => RD,
                8 => RQ,
                _ => return err!(val.pos, UnsupportedType(val_type.name())),
              }),
            },
          ),
        };
        let value = val_type.to_json(val.pos, memory.0)?;
        scope.extend(&self.mov_json(Rax, val.clone(), Some(scope.id))?);
        scope.extend(&ret_memory(memory, Rcx, Rax)?);
        self.drop_json(val.val, false, scope);
        if is_global {
          self.critical_sect(scope, LEAVE);
        }
        value
      }
    };
    if let Err(is_g) = reassign {
      let target = if is_g { &mut self.globals } else { scope.innermost() };
      let kind = if is_g { GlobalVar } else { LocalVar };
      target.insert(var.val, var.pos.with(Variable::new(value, kind)));
    }
    Ok(reassign.is_ok())
  }
  fn critical_sect(&mut self, scope: &mut Scope, action: &'static str) {
    let critical_section = Global(self.get_critical_section());
    scope.extend(&[LeaRM(Rcx, critical_section), CallApi(self.api(KERNEL32, action))]);
  }
  pub(crate) fn declare(
    &mut self,
    is_global: bool,
    func: &mut Pos<BuiltIn>,
    scope: &mut Scope,
  ) -> ErrOR<Json> {
    let mut assign_expr = arg!(func, (Object(Lit(x))) => x);
    if assign_expr.val.len() == 1
      && let (name, Pos { val: Array(Lit(mut expr)), .. }) = take(&mut assign_expr.val[0])
      && name.val == "="
      && expr.len() == 2
    {
      let var = take(&mut expr[0]).into_ident("Variable name")?;
      let val = self.eval(take(&mut expr[1]), scope)?;
      self.assign(Some(is_global), (var, val), scope)?;
      Ok(Null(Lit(())))
    } else {
      Err(type_err(
        format!("`{}`'s argument", func.val.name),
        vec![CustomT("Assign expression".into())],
        assign_expr.pos.with(ObjectT),
      ))
    }
  }
}
built_in! {self, func, scope, variable;
  assign_global => {"global", SPECIAL, Exact(1), { self.declare(true, func, scope) }},
  assign_local => {"let", SPECIAL, Exact(1), { self.declare(false, func, scope) }},
  reassign => {"=", SPECIAL, Exact(2), {
    let var = func.arg()?.into_ident("Variable name")?;
    let val = self.eval(func.arg()?, scope)?;
    if self.assign(None, (var.clone(), val), scope)? {
      Ok(Null(Lit(())))
    } else {
      err!(var.pos, UndefinedVar(var.val))
    }
  }},
  reference => {"$", COMMON, Exact(1), {
    Ok(self.get_var(&arg!(func, (Str(Lit(x))) => x), scope)?.val.val.clone())
  }},
  scope => {"scope", SP_SCOPE, Exact(1), {
    Ok(self.eval(func.arg()?, scope)?.val)
  }}
}