浏览代码

added some dynamic ops support

Nicolas Cannasse 8 年之前
父节点
当前提交
03c2808fca
共有 1 个文件被更改,包括 57 次插入0 次删除
  1. 57 0
      src/std/cast.c

+ 57 - 0
src/std/cast.c

@@ -393,9 +393,66 @@ HL_PRIM bool hl_type_safe_cast( hl_type *a, hl_type *b ) {
 	return hl_safe_cast(a,b);
 }
 
+#define NULL_VAL HLAST
+#define OP(op,t1,t2)	(TK2(t1,t2) | (op << 10))
+#define OP_ADD 0
+#define OP_SUB 1
+#define OP_MUL 2
+#define OP_MOD 3
+#define OP_DIV 4
+#define OP_SHL 5
+#define OP_SHR 6
+#define OP_USHR 7
+#define OP_AND 8
+#define OP_OR  9
+#define OP_XOR 10
+
+static vdynamic *hl_dynf64( double v ) {
+	vdynamic *d = hl_alloc_dynamic(&hlt_f64);
+	d->v.d = v;
+	return d;
+}
+
+static vdynamic *hl_dyni32( int v ) {
+	vdynamic *d = hl_alloc_dynamic(&hlt_i32);
+	d->v.i = v;
+	return d;
+}
+
+static bool is_number( hl_type *t ) {
+	return t->kind >= HUI8 && t->kind <= HBOOL;
+}
+
+#define FOP(op) { double va = hl_dyn_castd(a,&hlt_dyn); double vb = hl_dyn_castd(b,&hlt_dyn); return hl_dynf64(va op vb); }
+#define IOP(op) { int va = hl_dyn_casti(a,&hlt_dyn,&hlt_i32); int vb = hl_dyn_casti(b,&hlt_dyn,&hlt_i32); return hl_dyni32(va op vb); }
+
 HL_PRIM vdynamic *hl_dyn_op( int op, vdynamic *a, vdynamic *b ) {
 	static uchar *op_names[] = { USTR("+"), USTR("-"), USTR("*"), USTR("%"), USTR("/"), USTR("<<"), USTR(">>"), USTR(">>>"), USTR("&"), USTR("|"), USTR("^") };
 	if( op < 0 || op >= OpLast ) hl_error_msg(USTR("Invalid op %d"),op);
+	if( !a && !b ) return op == OP_DIV || op == OP_MOD ? hl_dynf64(hl_nan()) : NULL;
+	if( (!a || is_number(a->t)) && (!b || is_number(b->t)) ) {
+		switch( op ) {
+		case OP_ADD: FOP(+);
+		case OP_SUB: FOP(-);
+		case OP_MUL: FOP(*);
+		case OP_MOD: {
+			double va = hl_dyn_castd(a,&hlt_dyn);
+			double vb = hl_dyn_castd(b,&hlt_dyn);
+			return hl_dynf64(fmod(va,vb));
+		}
+		case OP_DIV: FOP(/);
+		case OP_SHL: IOP(<<);
+		case OP_SHR: IOP(>>);
+		case OP_USHR: {
+			int va = hl_dyn_casti(a,&hlt_dyn,&hlt_i32);
+			int vb = hl_dyn_casti(b,&hlt_dyn,&hlt_i32);
+			return hl_dyni32( ((unsigned)va) >> ((unsigned)vb) );
+		}
+		case OP_AND: IOP(&);
+		case OP_OR: IOP(|);
+		case OP_XOR: IOP(^);
+		}
+	}
 	hl_error_msg(USTR("Can't perform dyn op %s %s %s"),hl_type_str(a->t),op_names[op],hl_type_str(b->t));
 	return NULL;
 }