test change
diff --git a/src/sksl/SkSLByteCode.h b/src/sksl/SkSLByteCode.h
index adc4a0b..0ee7c62 100644
--- a/src/sksl/SkSLByteCode.h
+++ b/src/sksl/SkSLByteCode.h
@@ -21,7 +21,7 @@
 class ByteCode;
 class ExternalValue;
 
-class ByteCodeFunction {
+SK_API class ByteCodeFunction {
 public:
     // all counts are of 32-bit values, so a float4 counts as 4 parameter or return slots
     struct Parameter {
diff --git a/tests/SkSLInterpreterTest.cpp b/tests/SkSLInterpreterTest.cpp
index 9b2ab2c..6aac094 100644
--- a/tests/SkSLInterpreterTest.cpp
+++ b/tests/SkSLInterpreterTest.cpp
@@ -14,7 +14,7 @@
 
 #include "tests/Test.h"
 
-void test(skiatest::Reporter* r, const char* src, float* in, float* expected,
+void test(skiatest::Reporter* r, const char* src, int count, float* in, float* expected,
           bool exactCompare = true) {
     SkSL::Compiler compiler;
     SkSL::Program::Settings settings;
@@ -35,7 +35,10 @@
         SkSL::ByteCode::Vector<1>* result;
         bool success = interpreter.run(main, (SkSL::ByteCode::Vector<1>*) in, &result);
         REPORTER_ASSERT(r, success);
-        REPORTER_ASSERT(r, result->fFloat[0] == expected[0]);
+        for (int i = 0; i < count; ++i) {
+            printf("%d: expected %f, received %f\n", i, expected[i], result->fFloat[i]);
+            REPORTER_ASSERT(r, result->fFloat[i] == expected[i]);
+        }
     } else {
         printf("%s\n%s", src, compiler.errorText().c_str());
     }
@@ -155,7 +158,7 @@
     // Do additional testing of 4x1 vs 1x4 to stress divergent control flow, etc.
     vec_test(r, src);
 }
-
+/*
 DEF_TEST(SkSLInterpreterAdd, r) {
     test(r, "void main(inout half4 color) { color.r = color.r + color.g; }", 0.25, 0.75, 0, 0, 1,
          0.75, 0, 0);
@@ -907,341 +910,34 @@
     float expected[] = { cross.x, cross.y, cross.z };
     test(r, "float3 main(float3 x, float3 y) { return cross(x, y); }", args, expected);
 }
-
+*/
 DEF_TEST(SkSLInterpreterInverse, r) {
     {
+        printf("invert 2x2\n");
         SkMatrix m;
         m.setRotate(30).postScale(1, 2);
         float args[4] = { m[0], m[3], m[1], m[4] };
         SkAssertResult(m.invert(&m));
         float expt[4] = { m[0], m[3], m[1], m[4] };
-        test(r, "float2x2 main(float2x2 m) { return inverse(m); }", args, expt, false);
+        test(r, "float2x2 main(float2x2 m) { return inverse(m); }", 4, args, expt, false);
     }
     {
+        printf("invert 3x3\n");
         SkMatrix m;
         m.setRotate(30).postScale(1, 2).postTranslate(1, 2);
         float args[9] = { m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8] };
         SkAssertResult(m.invert(&m));
         float expt[9] = { m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8] };
-        test(r, "float3x3 main(float3x3 m) { return inverse(m); }", args, expt, false);
+        test(r, "float3x3 main(float3x3 m) { return inverse(m); }", 4, args, expt, false);
     }
     {
+        printf("invert 4x4\n");
         float args[16], expt[16];
         // just some crazy thing that is invertible
         SkM44 m = {1, 2, 3, 4, 1, 2, 0, 3, 1, 0, 1, 4, 1, 3, 2, 0};
         m.getColMajor(args);
         SkAssertResult(m.invert(&m));
-        m.getColMajor(expt);
-        test(r, "float4x4 main(float4x4 m) { return inverse(m); }", args, expt, false);
-    }
-}
-
-DEF_TEST(SkSLInterpreterDot, r) {
-    float args[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
-    float expected = args[0] * args[2] +
-                     args[1] * args[3];
-    test(r, "float main(float2 x, float2 y) { return dot(x, y); }", args, &expected);
-
-    expected = args[0] * args[3] +
-               args[1] * args[4] +
-               args[2] * args[5];
-    test(r, "float main(float3 x, float3 y) { return dot(x, y); }", args, &expected);
-
-    expected = args[0] * args[4] +
-               args[1] * args[5] +
-               args[2] * args[6] +
-               args[3] * args[7];
-    test(r, "float main(float4 x, float4 y) { return dot(x, y); }", args, &expected);
-}
-
-static const SkSL::Type& type_of(const skjson::Value* value, SkSL::Compiler* compiler) {
-    switch (value->getType()) {
-        case skjson::Value::Type::kNumber: {
-            float f = *value->as<skjson::NumberValue>();
-            if (f == (float) (int) f) {
-                return *compiler->context().fInt_Type;
-            }
-            return *compiler->context().fFloat_Type;
-        }
-        case skjson::Value::Type::kBool:
-            return *compiler->context().fBool_Type;
-        default:
-            return *compiler->context().fVoid_Type;
-    }
-}
-
-class JSONExternalValue : public SkSL::ExternalValue {
-public:
-    JSONExternalValue(const char* name, const skjson::Value* value, SkSL::Compiler* compiler)
-        : INHERITED(name, type_of(value, compiler))
-        , fValue(*value)
-        , fCompiler(*compiler) {}
-
-    bool canRead() const override {
-        return type() != *fCompiler.context().fVoid_Type;
-    }
-
-    void read(int /*unusedIndex*/, float* target) override {
-        if (type() == *fCompiler.context().fInt_Type) {
-            *(int*) target = *fValue.as<skjson::NumberValue>();
-        } else if (type() == *fCompiler.context().fFloat_Type) {
-            *(float*) target = *fValue.as<skjson::NumberValue>();
-        } else if (type() == *fCompiler.context().fBool_Type) {
-            // ByteCode "booleans" are actually bit-masks
-            *(int*) target = *fValue.as<skjson::BoolValue>() ? ~0 : 0;
-        } else {
-            SkASSERT(false);
-        }
-    }
-
-    SkSL::ExternalValue* getChild(const char* name) const override {
-        if (fValue.getType() == skjson::Value::Type::kObject) {
-            const skjson::Value& v = fValue.as<skjson::ObjectValue>()[name];
-            return (SkSL::ExternalValue*) fCompiler.takeOwnership(std::unique_ptr<Symbol>(
-                                                      new JSONExternalValue(name, &v, &fCompiler)));
-        }
-        return nullptr;
-    }
-
-private:
-    const skjson::Value& fValue;
-    SkSL::Compiler& fCompiler;
-
-    typedef SkSL::ExternalValue INHERITED;
-};
-
-class PointerExternalValue : public SkSL::ExternalValue {
-public:
-    PointerExternalValue(const char* name, const SkSL::Type& type, void* data, size_t size)
-        : INHERITED(name, type)
-        , fData(data)
-        , fSize(size) {}
-
-    bool canRead() const override {
-        return true;
-    }
-
-    bool canWrite() const override {
-        return true;
-    }
-
-    void read(int /*unusedIndex*/, float* target) override {
-        memcpy(target, fData, fSize);
-    }
-
-    void write(int /*unusedIndex*/, float* src) override {
-        memcpy(fData, src, fSize);
-    }
-
-
-private:
-    void* fData;
-    size_t fSize;
-
-    typedef SkSL::ExternalValue INHERITED;
-};
-
-DEF_TEST(SkSLInterpreterExternalValues, r) {
-    const char* json = "{ \"value1\": 12, \"child\": { \"value2\": true, \"value3\": 5.5 } }";
-    skjson::DOM dom(json, strlen(json));
-    SkSL::Compiler compiler;
-    SkSL::Program::Settings settings;
-    const char* src = "float main() {"
-                      "    outValue = 152;"
-                      "    return root.child.value2 ? root.value1 * root.child.value3 : -1;"
-                      "}";
-    compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
-             std::unique_ptr<SkSL::Symbol>(new JSONExternalValue("root", &dom.root(), &compiler))));
-    int32_t outValue = -1;
-    compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
-               std::unique_ptr<SkSL::Symbol>(new PointerExternalValue("outValue",
-                                                                      *compiler.context().fInt_Type,
-                                                                      &outValue,
-                                                                      sizeof(outValue)))));
-    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
-                                                             SkSL::Program::kGeneric_Kind,
-                                                             SkSL::String(src), settings);
-    REPORTER_ASSERT(r, program);
-    if (program) {
-        std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
-        REPORTER_ASSERT(r, !compiler.errorCount());
-        if (compiler.errorCount() > 0) {
-            printf("%s\n%s", src, compiler.errorText().c_str());
-            return;
-        }
-        const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
-        SkSL::Interpreter<1> interpreter(std::move(byteCode));
-        SkSL::ByteCode::Vector<1>* result;
-        bool success = interpreter.run(main, nullptr, &result);
-        REPORTER_ASSERT(r, success);
-        REPORTER_ASSERT(r, result->fFloat[0] == 66.0);
-        REPORTER_ASSERT(r, outValue == 152);
-    } else {
-        printf("%s\n%s", src, compiler.errorText().c_str());
-    }
-}
-
-DEF_TEST(SkSLInterpreterExternalValuesVector, r) {
-    SkSL::Compiler compiler;
-    SkSL::Program::Settings settings;
-    const char* src = "void main() {"
-                      "    value *= 2;"
-                      "}";
-    int32_t value[4] = { 1, 2, 3, 4 };
-    compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
-              std::unique_ptr<SkSL::Symbol>(new PointerExternalValue("value",
-                                                                     *compiler.context().fInt4_Type,
-                                                                     value,
-                                                                     sizeof(value)))));
-    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
-                                                                     SkSL::String(src),
-                                                                     settings);
-    REPORTER_ASSERT(r, program);
-    if (program) {
-        std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
-        REPORTER_ASSERT(r, !compiler.errorCount());
-        if (compiler.errorCount() > 0) {
-            printf("%s\n%s", src, compiler.errorText().c_str());
-            return;
-        }
-        const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
-        SkSL::Interpreter<1> interpreter(std::move(byteCode));
-        bool success = interpreter.run(main, nullptr, nullptr);
-        REPORTER_ASSERT(r, success);
-        REPORTER_ASSERT(r, value[0] == 2);
-        REPORTER_ASSERT(r, value[1] == 4);
-        REPORTER_ASSERT(r, value[2] == 6);
-        REPORTER_ASSERT(r, value[3] == 8);
-    } else {
-        printf("%s\n%s", src, compiler.errorText().c_str());
-    }
-}
-
-class FunctionExternalValue : public SkSL::ExternalValue {
-public:
-    FunctionExternalValue(const char* name, float(*function)(float), SkSL::Compiler& compiler)
-        : INHERITED(name, *compiler.context().fFloat_Type)
-        , fCompiler(compiler)
-        , fFunction(function) {}
-
-    bool canCall() const override {
-        return true;
-    }
-
-    int callParameterCount() const override {
-        return 1;
-    }
-
-    void getCallParameterTypes(const SkSL::Type** outTypes) const override {
-        outTypes[0] = fCompiler.context().fFloat_Type.get();
-    }
-
-    void call(int /*unusedIndex*/, float* arguments, float* outReturn) override {
-        outReturn[0] = fFunction(arguments[0]);
-    }
-
-private:
-    SkSL::Compiler& fCompiler;
-
-    float (*fFunction)(float);
-
-    typedef SkSL::ExternalValue INHERITED;
-};
-
-DEF_TEST(SkSLInterpreterExternalValuesCall, r) {
-    SkSL::Compiler compiler;
-    SkSL::Program::Settings settings;
-    const char* src = "float main() {"
-                      "    return external(25);"
-                      "}";
-    compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
-            std::unique_ptr<SkSL::Symbol>(new FunctionExternalValue("external",
-                                                                    [] (float x) {
-                                                                        return (float) sqrt(x);
-                                                                    },
-                                                                    compiler))));
-    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
-                                                                     SkSL::String(src),
-                                                                     settings);
-    REPORTER_ASSERT(r, program);
-    if (program) {
-        std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
-        REPORTER_ASSERT(r, !compiler.errorCount());
-        if (compiler.errorCount() > 0) {
-            printf("%s\n%s", src, compiler.errorText().c_str());
-            return;
-        }
-        const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
-        SkSL::Interpreter<1> interpreter(std::move(byteCode));
-        SkSL::ByteCode::Vector<1>* result;
-        bool success = interpreter.run(main, nullptr, &result);
-        REPORTER_ASSERT(r, success);
-        REPORTER_ASSERT(r, result->fFloat[0] == 5.0);
-    } else {
-        printf("%s\n%s", src, compiler.errorText().c_str());
-    }
-}
-
-class VectorFunctionExternalValue : public SkSL::ExternalValue {
-public:
-    VectorFunctionExternalValue(const char* name, void(*function)(float[4], float[4]),
-                                SkSL::Compiler& compiler)
-        : INHERITED(name, *compiler.context().fFloat4_Type)
-        , fCompiler(compiler)
-        , fFunction(function) {}
-    bool canCall() const override {
-        return true;
-    }
-    int callParameterCount() const override {
-        return 1;
-    }
-    void getCallParameterTypes(const SkSL::Type** outTypes) const override {
-        outTypes[0] = fCompiler.context().fFloat4_Type.get();
-    }
-    void call(int /*unusedIndex*/, float* arguments, float* outReturn) override {
-        fFunction(arguments, outReturn);
-    }
-private:
-    SkSL::Compiler& fCompiler;
-    void (*fFunction)(float[4], float[4]);
-    typedef SkSL::ExternalValue INHERITED;
-};
-DEF_TEST(SkSLInterpreterExternalValuesVectorCall, r) {
-    SkSL::Compiler compiler;
-    SkSL::Program::Settings settings;
-    const char* src = "float4 main() {"
-                      "    return external(float4(1, 4, 9, 16));"
-                      "}";
-    compiler.registerExternalValue((SkSL::ExternalValue*) compiler.takeOwnership(
-            std::unique_ptr<SkSL::Symbol>(new VectorFunctionExternalValue("external",
-                                                                    [] (float in[4], float out[4]) {
-                                                                        out[0] = sqrt(in[0]);
-                                                                        out[1] = sqrt(in[1]);
-                                                                        out[2] = sqrt(in[2]);
-                                                                        out[3] = sqrt(in[3]);
-                                                                    },
-                                                                    compiler))));
-    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
-                                                                     SkSL::String(src),
-                                                                     settings);
-    REPORTER_ASSERT(r, program);
-    if (program) {
-        std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
-        REPORTER_ASSERT(r, !compiler.errorCount());
-        if (compiler.errorCount() > 0) {
-            printf("%s\n%s", src, compiler.errorText().c_str());
-            return;
-        }
-        const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
-        SkSL::Interpreter<1> interpreter(std::move(byteCode));
-        SkSL::ByteCode::Vector<1>* result;
-        bool success = interpreter.run(main, nullptr, &result);
-        REPORTER_ASSERT(r, success);
-        REPORTER_ASSERT(r, result[0].fFloat[0] == 1.0);
-        REPORTER_ASSERT(r, result[1].fFloat[0] == 2.0);
-        REPORTER_ASSERT(r, result[2].fFloat[0] == 3.0);
-        REPORTER_ASSERT(r, result[3].fFloat[0] == 4.0);
-    } else {
-        printf("%s\n%s", src, compiler.errorText().c_str());
+        m.asColMajorf(expt);
+        test(r, "float4x4 main(float4x4 m) { return inverse(m); }", 4, args, expt, false);
     }
 }